Merge branch 'docker-image-login' of github.com:OSINTRoach/coolify into docker-image-login
2
.gitattributes
vendored
|
|
@ -8,4 +8,4 @@
|
|||
|
||||
/.github export-ignore
|
||||
CHANGELOG.md export-ignore
|
||||
.styleci.yml export-ignore
|
||||
.styleci.yml export-ignore
|
||||
|
|
@ -11,7 +11,7 @@ on:
|
|||
- docker/coolify-helper/Dockerfile
|
||||
- docker/coolify-realtime/Dockerfile
|
||||
- docker/testing-host/Dockerfile
|
||||
- templates/*
|
||||
- templates/**
|
||||
|
||||
env:
|
||||
GITHUB_REGISTRY: ghcr.io
|
||||
|
|
|
|||
2
.github/workflows/coolify-staging-build.yml
vendored
|
|
@ -11,7 +11,7 @@ on:
|
|||
- docker/coolify-helper/Dockerfile
|
||||
- docker/coolify-realtime/Dockerfile
|
||||
- docker/testing-host/Dockerfile
|
||||
- templates/*
|
||||
- templates/**
|
||||
|
||||
env:
|
||||
GITHUB_REGISTRY: ghcr.io
|
||||
|
|
|
|||
1
.gitignore
vendored
|
|
@ -35,3 +35,4 @@ scripts/load-test/*
|
|||
.ignition.json
|
||||
.env.dusk.local
|
||||
docker/coolify-realtime/node_modules
|
||||
.DS_Store
|
||||
|
|
|
|||
65
.gitpod.yml
|
|
@ -1,65 +0,0 @@
|
|||
tasks:
|
||||
- name: Setup Spin environment and Composer dependencies
|
||||
# Fix because of https://github.com/gitpod-io/gitpod/issues/16614
|
||||
before: sudo curl -o /usr/local/bin/docker-compose -fsSL https://github.com/docker/compose/releases/download/v2.16.0/docker-compose-linux-$(uname -m)
|
||||
init: |
|
||||
cp .env.development.example .env &&
|
||||
sed -i "s#APP_URL=http://localhost#APP_URL=$(gp url 8000)#g" .env
|
||||
sed -i "s#USERID=#USERID=33333#g" .env
|
||||
sed -i "s#GROUPID=#GROUPID=33333#g" .env
|
||||
composer install --ignore-platform-reqs
|
||||
./vendor/bin/spin up -d
|
||||
./vendor/bin/spin exec -u webuser coolify php artisan key:generate
|
||||
./vendor/bin/spin exec -u webuser coolify php artisan storage:link
|
||||
./vendor/bin/spin exec -u webuser coolify php artisan migrate:fresh --seed
|
||||
cat .coolify-logo
|
||||
gp sync-done spin-is-ready
|
||||
|
||||
- name: Install Node dependencies and run Vite
|
||||
command: |
|
||||
echo "Waiting for Sail environment to boot up."
|
||||
gp sync-await spin-is-ready
|
||||
./vendor/bin/spin exec vite npm install
|
||||
./vendor/bin/spin exec vite npm run dev -- --host
|
||||
|
||||
- name: Laravel Queue Worker, listening to code changes
|
||||
command: |
|
||||
echo "Waiting for Sail environment to boot up."
|
||||
gp sync-await spin-is-ready
|
||||
./vendor/bin/spin exec -u webuser coolify php artisan queue:listen
|
||||
|
||||
ports:
|
||||
- port: 5432
|
||||
onOpen: ignore
|
||||
name: PostgreSQL
|
||||
visibility: public
|
||||
- port: 5173
|
||||
onOpen: ignore
|
||||
visibility: public
|
||||
name: Node Server for Vite
|
||||
- port: 8000
|
||||
onOpen: ignore
|
||||
visibility: public
|
||||
name: Coolify
|
||||
|
||||
# Configure vscode
|
||||
vscode:
|
||||
extensions:
|
||||
- bmewburn.vscode-intelephense-client
|
||||
- ikappas.composer
|
||||
- ms-azuretools.vscode-docker
|
||||
- ecmel.vscode-html-css
|
||||
- MehediDracula.php-namespace-resolver
|
||||
- wmaurer.change-case
|
||||
- Equinusocio.vsc-community-material-theme
|
||||
- EditorConfig.EditorConfig
|
||||
- streetsidesoftware.code-spell-checker
|
||||
- rangav.vscode-thunder-client
|
||||
- PKief.material-icon-theme
|
||||
- cierra.livewire-vscode
|
||||
- lennardv.livewire-goto-updated
|
||||
- bradlc.vscode-tailwindcss
|
||||
- heybourn.headwind
|
||||
- adrianwilczynski.alpine-js-intellisense
|
||||
- amiralizadeh9480.laravel-extra-intellisense
|
||||
- shufo.vscode-blade-formatter
|
||||
11
README.md
|
|
@ -22,6 +22,9 @@ curl -fsSL https://cdn.coollabs.io/coolify/install.sh | bash
|
|||
```
|
||||
You can find the installation script source [here](./scripts/install.sh).
|
||||
|
||||
> [!NOTE]
|
||||
> Please refer to the [docs](https://coolify.io/docs/installation) for more information about the installation.
|
||||
|
||||
# Support
|
||||
|
||||
Contact us at [coolify.io/docs/contact](https://coolify.io/docs/contact).
|
||||
|
|
@ -121,7 +124,6 @@ By subscribing to the cloud version, you get the Coolify server for the same pri
|
|||
- Better support
|
||||
- Less maintenance for you
|
||||
|
||||
|
||||
# Recognitions
|
||||
|
||||
<p>
|
||||
|
|
@ -138,6 +140,13 @@ By subscribing to the cloud version, you get the Coolify server for the same pri
|
|||
|
||||
<a href="https://trendshift.io/repositories/634" target="_blank"><img src="https://trendshift.io/api/badge/repositories/634" alt="coollabsio%2Fcoolify | Trendshift" style="width: 250px; height: 55px;" width="250" height="55"/></a>
|
||||
|
||||
# Core Maintainers
|
||||
|
||||
| Andras Bacsai | Peak |
|
||||
|------------|------------|
|
||||
| <img src="https://github.com/andrasbacsai.png" width="200px" alt="Andras Bacsai" /> | <img src="https://github.com/peaklabs-dev.png" width="200px" alt="Peak Labs" /> |
|
||||
| <a href="https://x.com/heyandras"><img src="https://raw.githubusercontent.com/gauravghongde/social-icons/master/SVG/Color/Twitter.svg" width="25px"></a> <a href="https://github.com/andrasbacsai"><img src="https://raw.githubusercontent.com/gauravghongde/social-icons/master/SVG/Color/Github.svg" width="25px"></a> | <a href="https://x.com/peaklabs_dev"><img src="https://raw.githubusercontent.com/gauravghongde/social-icons/master/SVG/Color/Twitter.svg" width="25px"></a> <a href="https://github.com/peaklabs-dev"><img src="https://raw.githubusercontent.com/gauravghongde/social-icons/master/SVG/Color/Github.svg" width="25px"></a> |
|
||||
|
||||
# Repo Activity
|
||||
|
||||

|
||||
|
|
|
|||
33
RELEASE.md
|
|
@ -1,6 +1,6 @@
|
|||
# Coolify Release Guide
|
||||
|
||||
This guide outlines the release process for Coolify, intended for developers and those interested in understanding how releases are managed and deployed.
|
||||
This guide outlines the release process for Coolify, intended for developers and those interested in understanding how Coolify releases are managed and deployed.
|
||||
|
||||
## Table of Contents
|
||||
- [Release Process](#release-process)
|
||||
|
|
@ -19,19 +19,19 @@ This guide outlines the release process for Coolify, intended for developers and
|
|||
- Improvements, fixes, and new features are developed on the `next` branch or separate feature branches.
|
||||
|
||||
2. **Merging to `main`**
|
||||
- Once ready, changes are merged from the `next` branch into the `main` branch.
|
||||
- Once ready, changes are merged from the `next` branch into the `main` branch (via a pull request).
|
||||
|
||||
3. **Building the Release**
|
||||
- After merging to `main`, GitHub Actions automatically builds release images for all architectures and pushes them to the GitHub Container Registry with the version tag and the `latest` tag.
|
||||
- After merging to `main`, GitHub Actions automatically builds release images for all architectures and pushes them to the GitHub Container Registry and Docker Hub with the specific version tag and the `latest` tag.
|
||||
|
||||
4. **Creating a GitHub Release**
|
||||
- A new GitHub release is manually created with details of the changes made in the version.
|
||||
|
||||
5. **Updating the CDN**
|
||||
- To make a new version publicly available, the version information on the CDN needs to be updated: [https://cdn.coollabs.io/coolify/versions.json](https://cdn.coollabs.io/coolify/versions.json)
|
||||
- To make a new version publicly available, the version information on the CDN needs to be updated manually. After that the new version number will be available at [https://cdn.coollabs.io/coolify/versions.json](https://cdn.coollabs.io/coolify/versions.json).
|
||||
|
||||
> [!NOTE]
|
||||
> The CDN update may not occur immediately after the GitHub release. It can take hours or even days due to additional testing, stability checks, or potential hotfixes. **The update becomes available only after the CDN is updated.**
|
||||
> The CDN update may not occur immediately after the GitHub release. It can take hours or even days due to additional testing, stability checks, or potential hotfixes. **The update becomes available only after the CDN is updated. After the CDN is updated, a discord announcement will be made in the Production Release channel.**
|
||||
|
||||
## Version Types
|
||||
|
||||
|
|
@ -39,10 +39,10 @@ This guide outlines the release process for Coolify, intended for developers and
|
|||
<summary><strong>Stable (coming soon)</strong></summary>
|
||||
|
||||
- **Stable**
|
||||
- The production version suitable for stable, production environments (generally recommended).
|
||||
- **Update Frequency:** Every 2 to 4 weeks, with more frequent possible hotfixes.
|
||||
- The production version suitable for stable, production environments (recommended).
|
||||
- **Update Frequency:** Every 2 to 4 weeks, with more frequent possible fixes.
|
||||
- **Release Size:** Larger but less frequent releases. Multiple nightly versions are consolidated into a single stable release.
|
||||
- **Versioning Scheme:** Follows semantic versioning (e.g., `v4.0.0`).
|
||||
- **Versioning Scheme:** Follows semantic versioning (e.g., `v4.0.0`, `4.1.0`, etc.).
|
||||
- **Installation Command:**
|
||||
```bash
|
||||
curl -fsSL https://cdn.coollabs.io/coolify/install.sh | bash
|
||||
|
|
@ -57,7 +57,7 @@ This guide outlines the release process for Coolify, intended for developers and
|
|||
- The latest development version, suitable for testing the latest changes and experimenting with new features.
|
||||
- **Update Frequency:** Daily or bi-weekly updates.
|
||||
- **Release Size:** Smaller, more frequent releases.
|
||||
- **Versioning Scheme:** TO BE DETERMINED
|
||||
- **Versioning Scheme:** Follows semantic versioning (e.g., `4.1.0-nightly.1`, `4.1.0-nightly.2`, etc.).
|
||||
- **Installation Command:**
|
||||
```bash
|
||||
curl -fsSL https://cdn.coollabs.io/coolify-nightly/install.sh | bash -s next
|
||||
|
|
@ -73,11 +73,11 @@ This guide outlines the release process for Coolify, intended for developers and
|
|||
- **Purpose:** Allows users to test and provide feedback on new features and changes before they become stable.
|
||||
- **Update Frequency:** Available if we think beta testing is necessary.
|
||||
- **Release Size:** Same size as stable release as it will become the next stabe release after some time.
|
||||
- **Versioning Scheme:** Follows semantic versioning (e.g., `4.1.0-beta.1`).
|
||||
- **Versioning Scheme:** Follows semantic versioning (e.g., `4.1.0-beta.1`, `4.1.0-beta.2`, etc.).
|
||||
- **Installation Command:**
|
||||
```bash
|
||||
```bash
|
||||
curl -fsSL https://cdn.coollabs.io/coolify/install.sh | bash
|
||||
```
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
|
|
@ -117,12 +117,15 @@ When a new version is released and a new GitHub release is created, it doesn't i
|
|||
> [!IMPORTANT]
|
||||
> The cloud version of Coolify may be several versions behind the latest GitHub releases even if the CDN is updated. This is intentional to ensure stability and reliability for cloud users and Andras will manully update the cloud version when the update is ready.
|
||||
|
||||
## Manually Update to Specific Versions
|
||||
## Manually Update/ Downgrade to Specific Versions
|
||||
|
||||
> [!CAUTION]
|
||||
> Updating to unreleased versions is not recommended and may cause issues. Use at your own risk!
|
||||
> Updating to unreleased versions is not recommended and can cause issues.
|
||||
|
||||
To update your Coolify instance to a specific (unreleased) version, use the following command:
|
||||
> [!IMPORTANT]
|
||||
> Downgrading is supported but not recommended and can cause issues because of database migrations and other changes.
|
||||
|
||||
To update your Coolify instance to a specific version, use the following command:
|
||||
|
||||
```bash
|
||||
curl -fsSL https://cdn.coollabs.io/coolify/install.sh | bash -s <version>
|
||||
|
|
|
|||
23
SECURITY.md
|
|
@ -2,15 +2,24 @@
|
|||
|
||||
## Supported Versions
|
||||
|
||||
Use this section to tell people about which versions of your project are
|
||||
currently being supported with security updates.
|
||||
Currently supported, maintained and updated versions:
|
||||
|
||||
| Version | Supported |
|
||||
| ------- | ------------------ |
|
||||
| > 4 | :white_check_mark: |
|
||||
| 3 | :x: |
|
||||
| Version | Supported | Support Status |
|
||||
| ------- | ------------------ | -------------- |
|
||||
| 4.x | :white_check_mark: | Active Development & Security Updates |
|
||||
| < 4.0 | :x: | End of Life (no security updates) |
|
||||
|
||||
## Security Updates
|
||||
|
||||
We take security seriously. Security updates are released as soon as possible after a vulnerability is discovered and verified.
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
If you have any vulnerability please report at hi@coollabs.io
|
||||
If you discover a security vulnerability, please follow these steps:
|
||||
|
||||
1. **DO NOT** disclose the vulnerability publicly.
|
||||
2. Send a detailed report to: `hi@coollabs.io`.
|
||||
3. Include in your report:
|
||||
- A description of the vulnerability
|
||||
- Steps to reproduce the issue
|
||||
- Potential impact
|
||||
|
|
|
|||
37
app/Actions/Application/IsHorizonQueueEmpty.php
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
<?php
|
||||
|
||||
namespace App\Actions\Application;
|
||||
|
||||
use Laravel\Horizon\Contracts\JobRepository;
|
||||
use Lorisleiva\Actions\Concerns\AsAction;
|
||||
|
||||
class IsHorizonQueueEmpty
|
||||
{
|
||||
use AsAction;
|
||||
|
||||
public function handle()
|
||||
{
|
||||
$hostname = gethostname();
|
||||
$recent = app(JobRepository::class)->getRecent();
|
||||
if ($recent) {
|
||||
$running = $recent->filter(function ($job) use ($hostname) {
|
||||
$payload = json_decode($job->payload);
|
||||
$tags = data_get($payload, 'tags');
|
||||
|
||||
return $job->status != 'completed' &&
|
||||
$job->status != 'failed' &&
|
||||
isset($tags) &&
|
||||
is_array($tags) &&
|
||||
in_array('server:'.$hostname, $tags);
|
||||
});
|
||||
if ($running->count() > 0) {
|
||||
echo 'false';
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
echo 'true';
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,66 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Actions\License;
|
||||
|
||||
use Illuminate\Support\Facades\Http;
|
||||
use Lorisleiva\Actions\Concerns\AsAction;
|
||||
|
||||
class CheckResaleLicense
|
||||
{
|
||||
use AsAction;
|
||||
|
||||
public function handle()
|
||||
{
|
||||
try {
|
||||
$settings = instanceSettings();
|
||||
if (isDev()) {
|
||||
$settings->update([
|
||||
'is_resale_license_active' => true,
|
||||
]);
|
||||
|
||||
return;
|
||||
}
|
||||
// if (!$settings->resale_license) {
|
||||
// return;
|
||||
// }
|
||||
$base_url = config('coolify.license_url');
|
||||
$instance_id = config('app.id');
|
||||
$data = Http::withHeaders([
|
||||
'Accept' => 'application/json',
|
||||
])->get("$base_url/lemon/validate", [
|
||||
'license_key' => $settings->resale_license,
|
||||
'instance_id' => $instance_id,
|
||||
])->json();
|
||||
if (data_get($data, 'valid') === true && data_get($data, 'license_key.status') === 'active') {
|
||||
$settings->update([
|
||||
'is_resale_license_active' => true,
|
||||
]);
|
||||
|
||||
return;
|
||||
}
|
||||
$data = Http::withHeaders([
|
||||
'Accept' => 'application/json',
|
||||
])->get("$base_url/lemon/activate", [
|
||||
'license_key' => $settings->resale_license,
|
||||
'instance_id' => $instance_id,
|
||||
])->json();
|
||||
if (data_get($data, 'activated') === true) {
|
||||
$settings->update([
|
||||
'is_resale_license_active' => true,
|
||||
]);
|
||||
|
||||
return;
|
||||
}
|
||||
if (data_get($data, 'license_key.status') === 'active') {
|
||||
throw new \Exception('Invalid license key.');
|
||||
}
|
||||
throw new \Exception('Cannot activate license key.');
|
||||
} catch (\Throwable $e) {
|
||||
$settings->update([
|
||||
'resale_license' => null,
|
||||
'is_resale_license_active' => false,
|
||||
]);
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -13,7 +13,7 @@ class CleanupDocker
|
|||
{
|
||||
$settings = instanceSettings();
|
||||
$helperImageVersion = data_get($settings, 'helper_version');
|
||||
$helperImage = config('coolify.helper_image');
|
||||
$helperImage = config('constants.coolify.helper_image');
|
||||
$helperImageWithVersion = "$helperImage:$helperImageVersion";
|
||||
|
||||
$commands = [
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ class InstallDocker
|
|||
|
||||
public function handle(Server $server)
|
||||
{
|
||||
$dockerVersion = config('constants.docker_install_version');
|
||||
$dockerVersion = config('constants.docker.minimum_required_version');
|
||||
$supported_os_type = $server->validateOS();
|
||||
if (! $supported_os_type) {
|
||||
throw new \Exception('Server OS type is not supported for automated installation. Please install Docker manually before continuing: <a target="_blank" class="underline" href="https://coolify.io/docs/installation#manually">documentation</a>.');
|
||||
|
|
|
|||
|
|
@ -169,7 +169,7 @@ Files:
|
|||
');
|
||||
$license_key = $server->settings->logdrain_newrelic_license_key;
|
||||
$base_uri = $server->settings->logdrain_newrelic_base_uri;
|
||||
$base_path = config('coolify.base_config_path');
|
||||
$base_path = config('constants.coolify.base_config_path');
|
||||
|
||||
$config_path = $base_path.'/log-drains';
|
||||
$fluent_bit_config = $config_path.'/fluent-bit.conf';
|
||||
|
|
|
|||
49
app/Console/Commands/CloudCheckSubscription.php
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use App\Models\Team;
|
||||
use Illuminate\Console\Command;
|
||||
|
||||
class CloudCheckSubscription extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'cloud:check-subscription';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Check Cloud subscriptions';
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$stripe = new \Stripe\StripeClient(config('subscription.stripe_api_key'));
|
||||
$activeSubscribers = Team::whereRelation('subscription', 'stripe_invoice_paid', true)->get();
|
||||
foreach ($activeSubscribers as $team) {
|
||||
$stripeSubscriptionId = $team->subscription->stripe_subscription_id;
|
||||
$stripeInvoicePaid = $team->subscription->stripe_invoice_paid;
|
||||
$stripeCustomerId = $team->subscription->stripe_customer_id;
|
||||
if (! $stripeSubscriptionId) {
|
||||
echo "Team {$team->id} has no subscription, but invoice status is: {$stripeInvoicePaid}\n";
|
||||
echo "Link on Stripe: https://dashboard.stripe.com/customers/{$stripeCustomerId}\n";
|
||||
|
||||
continue;
|
||||
}
|
||||
$subscription = $stripe->subscriptions->retrieve($stripeSubscriptionId);
|
||||
if ($subscription->status === 'active') {
|
||||
continue;
|
||||
}
|
||||
echo "Subscription {$stripeSubscriptionId} is not active ({$subscription->status})\n";
|
||||
echo "Link on Stripe: https://dashboard.stripe.com/subscriptions/{$stripeSubscriptionId}\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -6,6 +6,7 @@ use App\Models\InstanceSettings;
|
|||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\Artisan;
|
||||
use Illuminate\Support\Facades\Process;
|
||||
use Symfony\Component\Yaml\Yaml;
|
||||
|
||||
class Dev extends Command
|
||||
{
|
||||
|
|
@ -31,19 +32,32 @@ class Dev extends Command
|
|||
{
|
||||
// Generate OpenAPI documentation
|
||||
echo "Generating OpenAPI documentation.\n";
|
||||
$process = Process::run(['/var/www/html/vendor/bin/openapi', 'app', '-o', 'openapi.yaml']);
|
||||
// https://github.com/OAI/OpenAPI-Specification/releases
|
||||
$process = Process::run([
|
||||
'/var/www/html/vendor/bin/openapi',
|
||||
'app',
|
||||
'-o',
|
||||
'openapi.yaml',
|
||||
'--version',
|
||||
'3.1.0',
|
||||
]);
|
||||
$error = $process->errorOutput();
|
||||
$error = preg_replace('/^.*an object literal,.*$/m', '', $error);
|
||||
$error = preg_replace('/^\h*\v+/m', '', $error);
|
||||
echo $error;
|
||||
echo $process->output();
|
||||
// Convert YAML to JSON
|
||||
$yaml = file_get_contents('openapi.yaml');
|
||||
$json = json_encode(Yaml::parse($yaml), JSON_PRETTY_PRINT);
|
||||
file_put_contents('openapi.json', $json);
|
||||
echo "Converted OpenAPI YAML to JSON.\n";
|
||||
}
|
||||
|
||||
public function init()
|
||||
{
|
||||
// Generate APP_KEY if not exists
|
||||
|
||||
if (empty(env('APP_KEY'))) {
|
||||
if (empty(config('app.key'))) {
|
||||
echo "Generating APP_KEY.\n";
|
||||
Artisan::call('key:generate');
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ class Horizon extends Command
|
|||
|
||||
public function handle()
|
||||
{
|
||||
if (config('coolify.is_horizon_enabled')) {
|
||||
if (config('constants.horizon.is_horizon_enabled')) {
|
||||
$this->info('Horizon is enabled. Starting.');
|
||||
$this->call('horizon');
|
||||
exit(0);
|
||||
|
|
|
|||
|
|
@ -57,12 +57,19 @@ class Init extends Command
|
|||
$this->call('cleanup:stucked-resources');
|
||||
|
||||
if (isCloud()) {
|
||||
$response = Http::retry(3, 1000)->get(config('constants.services.official'));
|
||||
if ($response->successful()) {
|
||||
$services = $response->json();
|
||||
File::put(base_path('templates/service-templates.json'), json_encode($services));
|
||||
try {
|
||||
$this->pullTemplatesFromCDN();
|
||||
} catch (\Throwable $e) {
|
||||
echo "Could not pull templates from CDN: {$e->getMessage()}\n";
|
||||
}
|
||||
}
|
||||
|
||||
if (! isCloud()) {
|
||||
try {
|
||||
$this->pullTemplatesFromCDN();
|
||||
} catch (\Throwable $e) {
|
||||
echo "Could not pull templates from CDN: {$e->getMessage()}\n";
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
$localhost = $this->servers->where('id', 0)->first();
|
||||
$localhost->setupDynamicProxyConfiguration();
|
||||
|
|
@ -70,8 +77,8 @@ class Init extends Command
|
|||
echo "Could not setup dynamic configuration: {$e->getMessage()}\n";
|
||||
}
|
||||
$settings = instanceSettings();
|
||||
if (! is_null(env('AUTOUPDATE', null))) {
|
||||
if (env('AUTOUPDATE') == true) {
|
||||
if (! is_null(config('constants.coolify.autoupdate', null))) {
|
||||
if (config('constants.coolify.autoupdate') == true) {
|
||||
$settings->update(['is_auto_update_enabled' => true]);
|
||||
} else {
|
||||
$settings->update(['is_auto_update_enabled' => false]);
|
||||
|
|
@ -80,6 +87,14 @@ class Init extends Command
|
|||
}
|
||||
}
|
||||
|
||||
private function pullTemplatesFromCDN()
|
||||
{
|
||||
$response = Http::retry(3, 1000)->get(config('constants.services.official'));
|
||||
if ($response->successful()) {
|
||||
$services = $response->json();
|
||||
File::put(base_path('templates/service-templates.json'), json_encode($services));
|
||||
}
|
||||
}
|
||||
// private function disable_metrics()
|
||||
// {
|
||||
// if (version_compare('4.0.0-beta.312', config('version'), '<=')) {
|
||||
|
|
|
|||
|
|
@ -15,7 +15,15 @@ class OpenApi extends Command
|
|||
{
|
||||
// Generate OpenAPI documentation
|
||||
echo "Generating OpenAPI documentation.\n";
|
||||
$process = Process::run(['/var/www/html/vendor/bin/openapi', 'app', '-o', 'openapi.yaml']);
|
||||
// https://github.com/OAI/OpenAPI-Specification/releases
|
||||
$process = Process::run([
|
||||
'/var/www/html/vendor/bin/openapi',
|
||||
'app',
|
||||
'-o',
|
||||
'openapi.yaml',
|
||||
'--version',
|
||||
'3.1.0',
|
||||
]);
|
||||
$error = $process->errorOutput();
|
||||
$error = preg_replace('/^.*an object literal,.*$/m', '', $error);
|
||||
$error = preg_replace('/^\h*\v+/m', '', $error);
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ class Scheduler extends Command
|
|||
|
||||
public function handle()
|
||||
{
|
||||
if (config('coolify.is_scheduler_enabled')) {
|
||||
if (config('constants.horizon.is_scheduler_enabled')) {
|
||||
$this->info('Scheduler is enabled. Starting.');
|
||||
$this->call('schedule:work');
|
||||
exit(0);
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ class SyncBunny extends Command
|
|||
|
||||
PendingRequest::macro('storage', function ($fileName) use ($that) {
|
||||
$headers = [
|
||||
'AccessKey' => env('BUNNY_STORAGE_API_KEY'),
|
||||
'AccessKey' => config('constants.bunny.storage_api_key'),
|
||||
'Accept' => 'application/json',
|
||||
'Content-Type' => 'application/octet-stream',
|
||||
];
|
||||
|
|
@ -69,7 +69,7 @@ class SyncBunny extends Command
|
|||
});
|
||||
PendingRequest::macro('purge', function ($url) use ($that) {
|
||||
$headers = [
|
||||
'AccessKey' => env('BUNNY_API_KEY'),
|
||||
'AccessKey' => config('constants.bunny.api_key'),
|
||||
'Accept' => 'application/json',
|
||||
];
|
||||
$that->info('Purging: '.$url);
|
||||
|
|
|
|||
|
|
@ -28,6 +28,8 @@ class Kernel extends ConsoleKernel
|
|||
{
|
||||
private $allServers;
|
||||
|
||||
private Schedule $scheduleInstance;
|
||||
|
||||
private InstanceSettings $settings;
|
||||
|
||||
private string $updateCheckFrequency;
|
||||
|
|
@ -36,82 +38,90 @@ class Kernel extends ConsoleKernel
|
|||
|
||||
protected function schedule(Schedule $schedule): void
|
||||
{
|
||||
$this->scheduleInstance = $schedule;
|
||||
$this->allServers = Server::where('ip', '!=', '1.2.3.4');
|
||||
|
||||
$this->settings = instanceSettings();
|
||||
$this->updateCheckFrequency = $this->settings->update_check_frequency ?: '0 * * * *';
|
||||
|
||||
$this->instanceTimezone = $this->settings->instance_timezone ?: config('app.timezone');
|
||||
|
||||
$schedule->job(new CleanupStaleMultiplexedConnections)->hourly();
|
||||
if (validate_timezone($this->instanceTimezone) === false) {
|
||||
$this->instanceTimezone = config('app.timezone');
|
||||
}
|
||||
|
||||
$this->scheduleInstance->job(new CleanupStaleMultiplexedConnections)->hourly();
|
||||
|
||||
if (isDev()) {
|
||||
// Instance Jobs
|
||||
$schedule->command('horizon:snapshot')->everyMinute();
|
||||
$schedule->job(new CleanupInstanceStuffsJob)->everyMinute()->onOneServer();
|
||||
$schedule->job(new CheckHelperImageJob)->everyTenMinutes()->onOneServer();
|
||||
$this->scheduleInstance->command('horizon:snapshot')->everyMinute();
|
||||
$this->scheduleInstance->job(new CleanupInstanceStuffsJob)->everyMinute()->onOneServer();
|
||||
$this->scheduleInstance->job(new CheckHelperImageJob)->everyTenMinutes()->onOneServer();
|
||||
|
||||
// Server Jobs
|
||||
$this->checkResources($schedule);
|
||||
$this->checkResources();
|
||||
|
||||
$this->checkScheduledBackups($schedule);
|
||||
$this->checkScheduledTasks($schedule);
|
||||
$this->checkScheduledBackups();
|
||||
$this->checkScheduledTasks();
|
||||
|
||||
$schedule->command('uploads:clear')->everyTwoMinutes();
|
||||
$this->scheduleInstance->command('uploads:clear')->everyTwoMinutes();
|
||||
|
||||
} else {
|
||||
// Instance Jobs
|
||||
$schedule->command('horizon:snapshot')->everyFiveMinutes();
|
||||
$schedule->command('cleanup:unreachable-servers')->daily()->onOneServer();
|
||||
$schedule->job(new PullTemplatesFromCDN)->cron($this->updateCheckFrequency)->timezone($this->instanceTimezone)->onOneServer();
|
||||
$schedule->job(new CleanupInstanceStuffsJob)->everyTwoMinutes()->onOneServer();
|
||||
$this->scheduleUpdates($schedule);
|
||||
$this->scheduleInstance->command('horizon:snapshot')->everyFiveMinutes();
|
||||
$this->scheduleInstance->command('cleanup:unreachable-servers')->daily()->onOneServer();
|
||||
|
||||
$this->scheduleInstance->job(new PullTemplatesFromCDN)->cron($this->updateCheckFrequency)->timezone($this->instanceTimezone)->onOneServer();
|
||||
|
||||
$this->scheduleInstance->job(new CleanupInstanceStuffsJob)->everyTwoMinutes()->onOneServer();
|
||||
$this->scheduleUpdates();
|
||||
|
||||
// Server Jobs
|
||||
$this->checkResources($schedule);
|
||||
$this->checkResources();
|
||||
|
||||
$this->pullImages($schedule);
|
||||
$this->pullImages();
|
||||
|
||||
$this->checkScheduledBackups($schedule);
|
||||
$this->checkScheduledTasks($schedule);
|
||||
$this->checkScheduledBackups();
|
||||
$this->checkScheduledTasks();
|
||||
|
||||
$schedule->command('cleanup:database --yes')->daily();
|
||||
$schedule->command('uploads:clear')->everyTwoMinutes();
|
||||
$this->scheduleInstance->command('cleanup:database --yes')->daily();
|
||||
$this->scheduleInstance->command('uploads:clear')->everyTwoMinutes();
|
||||
}
|
||||
}
|
||||
|
||||
private function pullImages($schedule): void
|
||||
private function pullImages(): void
|
||||
{
|
||||
$servers = $this->allServers->whereRelation('settings', 'is_usable', true)->whereRelation('settings', 'is_reachable', true)->get();
|
||||
foreach ($servers as $server) {
|
||||
if ($server->isSentinelEnabled()) {
|
||||
$schedule->job(function () use ($server) {
|
||||
$this->scheduleInstance->job(function () use ($server) {
|
||||
CheckAndStartSentinelJob::dispatch($server);
|
||||
})->cron($this->updateCheckFrequency)->timezone($this->instanceTimezone)->onOneServer();
|
||||
}
|
||||
}
|
||||
$schedule->job(new CheckHelperImageJob)
|
||||
$this->scheduleInstance->job(new CheckHelperImageJob)
|
||||
->cron($this->updateCheckFrequency)
|
||||
->timezone($this->instanceTimezone)
|
||||
->onOneServer();
|
||||
}
|
||||
|
||||
private function scheduleUpdates($schedule): void
|
||||
private function scheduleUpdates(): void
|
||||
{
|
||||
$schedule->job(new CheckForUpdatesJob)
|
||||
$this->scheduleInstance->job(new CheckForUpdatesJob)
|
||||
->cron($this->updateCheckFrequency)
|
||||
->timezone($this->instanceTimezone)
|
||||
->onOneServer();
|
||||
|
||||
if ($this->settings->is_auto_update_enabled) {
|
||||
$autoUpdateFrequency = $this->settings->auto_update_frequency;
|
||||
$schedule->job(new UpdateCoolifyJob)
|
||||
$this->scheduleInstance->job(new UpdateCoolifyJob)
|
||||
->cron($autoUpdateFrequency)
|
||||
->timezone($this->instanceTimezone)
|
||||
->onOneServer();
|
||||
}
|
||||
}
|
||||
|
||||
private function checkResources($schedule): void
|
||||
private function checkResources(): void
|
||||
{
|
||||
if (isCloud()) {
|
||||
$servers = $this->allServers->whereHas('team.subscription')->get();
|
||||
|
|
@ -128,31 +138,34 @@ class Kernel extends ConsoleKernel
|
|||
$lastSentinelUpdate = $server->sentinel_updated_at;
|
||||
if (Carbon::parse($lastSentinelUpdate)->isBefore(now()->subSeconds($server->waitBeforeDoingSshCheck()))) {
|
||||
// Check container status every minute if Sentinel does not activated
|
||||
$schedule->job(new ServerCheckJob($server))->everyMinute()->onOneServer();
|
||||
// $schedule->job(new \App\Jobs\ServerCheckNewJob($server))->everyMinute()->onOneServer();
|
||||
if (validate_timezone($serverTimezone) === false) {
|
||||
$serverTimezone = config('app.timezone');
|
||||
}
|
||||
$this->scheduleInstance->job(new ServerCheckJob($server))->timezone($serverTimezone)->everyMinute()->onOneServer();
|
||||
// $this->scheduleInstance->job(new \App\Jobs\ServerCheckNewJob($server))->everyMinute()->onOneServer();
|
||||
|
||||
// Check storage usage every 10 minutes if Sentinel does not activated
|
||||
$schedule->job(new ServerStorageCheckJob($server))->everyTenMinutes()->onOneServer();
|
||||
$this->scheduleInstance->job(new ServerStorageCheckJob($server))->everyTenMinutes()->onOneServer();
|
||||
}
|
||||
if ($server->settings->force_docker_cleanup) {
|
||||
$schedule->job(new DockerCleanupJob($server))->cron($server->settings->docker_cleanup_frequency)->timezone($serverTimezone)->onOneServer();
|
||||
$this->scheduleInstance->job(new DockerCleanupJob($server))->cron($server->settings->docker_cleanup_frequency)->timezone($serverTimezone)->onOneServer();
|
||||
} else {
|
||||
$schedule->job(new DockerCleanupJob($server))->everyTenMinutes()->timezone($serverTimezone)->onOneServer();
|
||||
$this->scheduleInstance->job(new DockerCleanupJob($server))->everyTenMinutes()->timezone($serverTimezone)->onOneServer();
|
||||
}
|
||||
|
||||
// Cleanup multiplexed connections every hour
|
||||
$schedule->job(new ServerCleanupMux($server))->hourly()->onOneServer();
|
||||
$this->scheduleInstance->job(new ServerCleanupMux($server))->hourly()->onOneServer();
|
||||
|
||||
// Temporary solution until we have better memory management for Sentinel
|
||||
if ($server->isSentinelEnabled()) {
|
||||
$schedule->job(function () use ($server) {
|
||||
$this->scheduleInstance->job(function () use ($server) {
|
||||
$server->restartContainer('coolify-sentinel');
|
||||
})->daily()->onOneServer();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function checkScheduledBackups($schedule): void
|
||||
private function checkScheduledBackups(): void
|
||||
{
|
||||
$scheduled_backups = ScheduledDatabaseBackup::where('enabled', true)->get();
|
||||
if ($scheduled_backups->isEmpty()) {
|
||||
|
|
@ -174,13 +187,13 @@ class Kernel extends ConsoleKernel
|
|||
if (isset(VALID_CRON_STRINGS[$scheduled_backup->frequency])) {
|
||||
$scheduled_backup->frequency = VALID_CRON_STRINGS[$scheduled_backup->frequency];
|
||||
}
|
||||
$schedule->job(new DatabaseBackupJob(
|
||||
$this->scheduleInstance->job(new DatabaseBackupJob(
|
||||
backup: $scheduled_backup
|
||||
))->cron($scheduled_backup->frequency)->timezone($this->instanceTimezone)->onOneServer();
|
||||
}
|
||||
}
|
||||
|
||||
private function checkScheduledTasks($schedule): void
|
||||
private function checkScheduledTasks(): void
|
||||
{
|
||||
$scheduled_tasks = ScheduledTask::where('enabled', true)->get();
|
||||
if ($scheduled_tasks->isEmpty()) {
|
||||
|
|
@ -214,7 +227,7 @@ class Kernel extends ConsoleKernel
|
|||
if (isset(VALID_CRON_STRINGS[$scheduled_task->frequency])) {
|
||||
$scheduled_task->frequency = VALID_CRON_STRINGS[$scheduled_task->frequency];
|
||||
}
|
||||
$schedule->job(new ScheduledTaskJob(
|
||||
$this->scheduleInstance->job(new ScheduledTaskJob(
|
||||
task: $scheduled_task
|
||||
))->cron($scheduled_task->frequency)->timezone($this->instanceTimezone)->onOneServer();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -151,7 +151,7 @@ class SshMultiplexingHelper
|
|||
|
||||
private static function isMultiplexingEnabled(): bool
|
||||
{
|
||||
return config('constants.ssh.mux_enabled') && ! config('coolify.is_windows_docker_desktop');
|
||||
return config('constants.ssh.mux_enabled') && ! config('constants.coolify.is_windows_docker_desktop');
|
||||
}
|
||||
|
||||
private static function validateSshKey(string $sshKeyLocation): void
|
||||
|
|
|
|||
|
|
@ -147,7 +147,7 @@ class OtherController extends Controller
|
|||
public function feedback(Request $request)
|
||||
{
|
||||
$content = $request->input('content');
|
||||
$webhook_url = config('coolify.feedback_discord_webhook');
|
||||
$webhook_url = config('constants.webhooks.feedback_discord_webhook');
|
||||
if ($webhook_url) {
|
||||
Http::post($webhook_url, [
|
||||
'content' => $content,
|
||||
|
|
|
|||
|
|
@ -116,7 +116,7 @@ class ProjectController extends Controller
|
|||
responses: [
|
||||
new OA\Response(
|
||||
response: 200,
|
||||
description: 'Project details',
|
||||
description: 'Environment details',
|
||||
content: new OA\JsonContent(ref: '#/components/schemas/Environment')),
|
||||
new OA\Response(
|
||||
response: 401,
|
||||
|
|
|
|||
|
|
@ -81,15 +81,8 @@ class SecurityController extends Controller
|
|||
new OA\Response(
|
||||
response: 200,
|
||||
description: 'Get all private keys.',
|
||||
content: [
|
||||
new OA\MediaType(
|
||||
mediaType: 'application/json',
|
||||
schema: new OA\Schema(
|
||||
type: 'array',
|
||||
items: new OA\Items(ref: '#/components/schemas/PrivateKey')
|
||||
)
|
||||
),
|
||||
]),
|
||||
content: new OA\JsonContent(ref: '#/components/schemas/PrivateKey')
|
||||
),
|
||||
new OA\Response(
|
||||
response: 401,
|
||||
ref: '#/components/responses/401',
|
||||
|
|
|
|||
|
|
@ -426,6 +426,7 @@ class ServersController extends Controller
|
|||
'private_key_uuid' => ['type' => 'string', 'example' => 'og888os', 'description' => 'The UUID of the private key.'],
|
||||
'is_build_server' => ['type' => 'boolean', 'example' => false, 'description' => 'Is build server.'],
|
||||
'instant_validate' => ['type' => 'boolean', 'example' => false, 'description' => 'Instant validate.'],
|
||||
'proxy_type' => ['type' => 'string', 'enum' => ['traefik', 'caddy', 'none'], 'example' => 'traefik', 'description' => 'The proxy type.'],
|
||||
],
|
||||
),
|
||||
),
|
||||
|
|
@ -461,7 +462,7 @@ class ServersController extends Controller
|
|||
)]
|
||||
public function create_server(Request $request)
|
||||
{
|
||||
$allowedFields = ['name', 'description', 'ip', 'port', 'user', 'private_key_uuid', 'is_build_server', 'instant_validate'];
|
||||
$allowedFields = ['name', 'description', 'ip', 'port', 'user', 'private_key_uuid', 'is_build_server', 'instant_validate', 'proxy_type'];
|
||||
|
||||
$teamId = getTeamIdFromToken();
|
||||
if (is_null($teamId)) {
|
||||
|
|
@ -481,6 +482,7 @@ class ServersController extends Controller
|
|||
'user' => 'string|nullable',
|
||||
'is_build_server' => 'boolean|nullable',
|
||||
'instant_validate' => 'boolean|nullable',
|
||||
'proxy_type' => 'string|nullable',
|
||||
]);
|
||||
|
||||
$extraFields = array_diff(array_keys($request->all()), $allowedFields);
|
||||
|
|
@ -512,6 +514,14 @@ class ServersController extends Controller
|
|||
if (is_null($request->instant_validate)) {
|
||||
$request->offsetSet('instant_validate', false);
|
||||
}
|
||||
if ($request->proxy_type) {
|
||||
$validProxyTypes = collect(ProxyTypes::cases())->map(function ($proxyType) {
|
||||
return str($proxyType->value)->lower();
|
||||
});
|
||||
if (! $validProxyTypes->contains(str($request->proxy_type)->lower())) {
|
||||
return response()->json(['message' => 'Invalid proxy type.'], 422);
|
||||
}
|
||||
}
|
||||
$privateKey = PrivateKey::whereTeamId($teamId)->whereUuid($request->private_key_uuid)->first();
|
||||
if (! $privateKey) {
|
||||
return response()->json(['message' => 'Private key not found.'], 404);
|
||||
|
|
@ -521,6 +531,8 @@ class ServersController extends Controller
|
|||
return response()->json(['message' => 'Server with this IP already exists.'], 400);
|
||||
}
|
||||
|
||||
$proxyType = $request->proxy_type ? str($request->proxy_type)->upper() : ProxyTypes::TRAEFIK->value;
|
||||
|
||||
$server = ModelsServer::create([
|
||||
'name' => $request->name,
|
||||
'description' => $request->description,
|
||||
|
|
@ -530,7 +542,7 @@ class ServersController extends Controller
|
|||
'private_key_id' => $privateKey->id,
|
||||
'team_id' => $teamId,
|
||||
'proxy' => [
|
||||
'type' => ProxyTypes::TRAEFIK->value,
|
||||
'type' => $proxyType,
|
||||
'status' => ProxyStatus::EXITED->value,
|
||||
],
|
||||
]);
|
||||
|
|
@ -571,6 +583,7 @@ class ServersController extends Controller
|
|||
'private_key_uuid' => ['type' => 'string', 'description' => 'The UUID of the private key.'],
|
||||
'is_build_server' => ['type' => 'boolean', 'description' => 'Is build server.'],
|
||||
'instant_validate' => ['type' => 'boolean', 'description' => 'Instant validate.'],
|
||||
'proxy_type' => ['type' => 'string', 'enum' => ['traefik', 'caddy', 'none'], 'description' => 'The proxy type.'],
|
||||
],
|
||||
),
|
||||
),
|
||||
|
|
@ -604,7 +617,7 @@ class ServersController extends Controller
|
|||
)]
|
||||
public function update_server(Request $request)
|
||||
{
|
||||
$allowedFields = ['name', 'description', 'ip', 'port', 'user', 'private_key_uuid', 'is_build_server', 'instant_validate'];
|
||||
$allowedFields = ['name', 'description', 'ip', 'port', 'user', 'private_key_uuid', 'is_build_server', 'instant_validate', 'proxy_type'];
|
||||
|
||||
$teamId = getTeamIdFromToken();
|
||||
if (is_null($teamId)) {
|
||||
|
|
@ -624,6 +637,7 @@ class ServersController extends Controller
|
|||
'user' => 'string|nullable',
|
||||
'is_build_server' => 'boolean|nullable',
|
||||
'instant_validate' => 'boolean|nullable',
|
||||
'proxy_type' => 'string|nullable',
|
||||
]);
|
||||
|
||||
$extraFields = array_diff(array_keys($request->all()), $allowedFields);
|
||||
|
|
@ -644,6 +658,16 @@ class ServersController extends Controller
|
|||
if (! $server) {
|
||||
return response()->json(['message' => 'Server not found.'], 404);
|
||||
}
|
||||
if ($request->proxy_type) {
|
||||
$validProxyTypes = collect(ProxyTypes::cases())->map(function ($proxyType) {
|
||||
return str($proxyType->value)->lower();
|
||||
});
|
||||
if ($validProxyTypes->contains(str($request->proxy_type)->lower())) {
|
||||
$server->changeProxy($request->proxy_type, async: true);
|
||||
} else {
|
||||
return response()->json(['message' => 'Invalid proxy type.'], 422);
|
||||
}
|
||||
}
|
||||
$server->update($request->only(['name', 'description', 'ip', 'port', 'user']));
|
||||
if ($request->is_build_server) {
|
||||
$server->settings()->update([
|
||||
|
|
@ -654,7 +678,9 @@ class ServersController extends Controller
|
|||
ValidateServer::dispatch($server)->onQueue('high');
|
||||
}
|
||||
|
||||
return response()->json(serializeApiResponse($server))->setStatusCode(201);
|
||||
return response()->json([
|
||||
|
||||
])->setStatusCode(201);
|
||||
}
|
||||
|
||||
#[OA\Delete(
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ class Gitlab extends Controller
|
|||
|
||||
return;
|
||||
}
|
||||
|
||||
$return_payloads = collect([]);
|
||||
$payload = $request->collect();
|
||||
$headers = $request->headers->all();
|
||||
|
|
@ -48,6 +49,15 @@ class Gitlab extends Controller
|
|||
return response($return_payloads);
|
||||
}
|
||||
|
||||
if (empty($x_gitlab_token)) {
|
||||
$return_payloads->push([
|
||||
'status' => 'failed',
|
||||
'message' => 'Invalid signature.',
|
||||
]);
|
||||
|
||||
return response($return_payloads);
|
||||
}
|
||||
|
||||
if ($x_gitlab_event === 'push') {
|
||||
$branch = data_get($payload, 'ref');
|
||||
$full_name = data_get($payload, 'project.path_with_namespace');
|
||||
|
|
|
|||
|
|
@ -5,8 +5,6 @@ namespace App\Http\Controllers\Webhook;
|
|||
use App\Http\Controllers\Controller;
|
||||
use App\Jobs\ServerLimitCheckJob;
|
||||
use App\Jobs\SubscriptionInvoiceFailedJob;
|
||||
use App\Jobs\SubscriptionTrialEndedJob;
|
||||
use App\Jobs\SubscriptionTrialEndsSoonJob;
|
||||
use App\Models\Subscription;
|
||||
use App\Models\Team;
|
||||
use App\Models\Webhook;
|
||||
|
|
@ -260,42 +258,7 @@ class Stripe extends Controller
|
|||
$customerId = data_get($data, 'customer');
|
||||
$subscription = Subscription::where('stripe_customer_id', $customerId)->firstOrFail();
|
||||
$team = data_get($subscription, 'team');
|
||||
if ($team) {
|
||||
$team->trialEnded();
|
||||
}
|
||||
$subscription->update([
|
||||
'stripe_subscription_id' => null,
|
||||
'stripe_plan_id' => null,
|
||||
'stripe_cancel_at_period_end' => false,
|
||||
'stripe_invoice_paid' => false,
|
||||
'stripe_trial_already_ended' => false,
|
||||
]);
|
||||
// send_internal_notification('customer.subscription.deleted for customer: '.$customerId);
|
||||
break;
|
||||
case 'customer.subscription.trial_will_end':
|
||||
// Not used for now
|
||||
$customerId = data_get($data, 'customer');
|
||||
$subscription = Subscription::where('stripe_customer_id', $customerId)->firstOrFail();
|
||||
$team = data_get($subscription, 'team');
|
||||
if (! $team) {
|
||||
return response('No team found for subscription: '.$subscription->id, 400);
|
||||
}
|
||||
SubscriptionTrialEndsSoonJob::dispatch($team);
|
||||
break;
|
||||
case 'customer.subscription.paused':
|
||||
$customerId = data_get($data, 'customer');
|
||||
$subscription = Subscription::where('stripe_customer_id', $customerId)->firstOrFail();
|
||||
$team = data_get($subscription, 'team');
|
||||
if (! $team) {
|
||||
return response('No team found for subscription: '.$subscription->id, 400);
|
||||
}
|
||||
$team->trialEnded();
|
||||
$subscription->update([
|
||||
'stripe_trial_already_ended' => true,
|
||||
'stripe_invoice_paid' => false,
|
||||
]);
|
||||
SubscriptionTrialEndedJob::dispatch($team);
|
||||
// send_internal_notification('Subscription paused for customer: '.$customerId);
|
||||
$team?->subscriptionEnded();
|
||||
break;
|
||||
default:
|
||||
// Unhandled event type
|
||||
|
|
|
|||
|
|
@ -226,6 +226,11 @@ class ApplicationDeploymentJob implements ShouldBeEncrypted, ShouldQueue
|
|||
}
|
||||
}
|
||||
|
||||
public function tags(): array
|
||||
{
|
||||
return ['server:'.gethostname()];
|
||||
}
|
||||
|
||||
public function handle(): void
|
||||
{
|
||||
$this->application_deployment_queue->update([
|
||||
|
|
@ -1341,7 +1346,7 @@ class ApplicationDeploymentJob implements ShouldBeEncrypted, ShouldQueue
|
|||
private function prepare_builder_image()
|
||||
{
|
||||
$settings = instanceSettings();
|
||||
$helperImage = config('coolify.helper_image');
|
||||
$helperImage = config('constants.coolify.helper_image');
|
||||
$helperImage = "{$helperImage}:{$settings->helper_version}";
|
||||
// Get user home directory
|
||||
$this->serverUserHomeDir = instant_remote_process(['echo $HOME'], $this->server);
|
||||
|
|
@ -2011,7 +2016,7 @@ WORKDIR /usr/share/nginx/html/
|
|||
LABEL coolify.deploymentId={$this->deployment_uuid}
|
||||
COPY . .
|
||||
RUN rm -f /usr/share/nginx/html/nginx.conf
|
||||
RUN rm -f /usr/share/nginx/html/Dockerfile`
|
||||
RUN rm -f /usr/share/nginx/html/Dockerfile
|
||||
COPY ./nginx.conf /etc/nginx/conf.d/default.conf");
|
||||
if (str($this->application->custom_nginx_configuration)->isNotEmpty()) {
|
||||
$nginx_config = base64_encode($this->application->custom_nginx_configuration);
|
||||
|
|
|
|||
|
|
@ -524,7 +524,7 @@ class DatabaseBackupJob implements ShouldBeEncrypted, ShouldQueue
|
|||
private function getFullImageName(): string
|
||||
{
|
||||
$settings = instanceSettings();
|
||||
$helperImage = config('coolify.helper_image');
|
||||
$helperImage = config('constants.coolify.helper_image');
|
||||
$latestVersion = $settings->helper_version;
|
||||
|
||||
return "{$helperImage}:{$latestVersion}";
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ class DockerCleanupJob implements ShouldBeEncrypted, ShouldQueue
|
|||
|
||||
public function middleware(): array
|
||||
{
|
||||
return [(new WithoutOverlapping($this->server->id))->dontRelease()];
|
||||
return [(new WithoutOverlapping($this->server->uuid))->dontRelease()];
|
||||
}
|
||||
|
||||
public function __construct(public Server $server, public bool $manualCleanup = false) {}
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ class PullHelperImageJob implements ShouldBeEncrypted, ShouldQueue
|
|||
|
||||
public function handle(): void
|
||||
{
|
||||
$helperImage = config('coolify.helper_image');
|
||||
$helperImage = config('constants.coolify.helper_image');
|
||||
$latest_version = instanceSettings()->helper_version;
|
||||
instant_remote_process(["docker pull -q {$helperImage}:{$latest_version}"], $this->server, false);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ class ServerCheckJob implements ShouldBeEncrypted, ShouldQueue
|
|||
|
||||
public function middleware(): array
|
||||
{
|
||||
return [(new WithoutOverlapping($this->server->id))->dontRelease()];
|
||||
return [(new WithoutOverlapping($this->server->uuid))->dontRelease()];
|
||||
}
|
||||
|
||||
public function __construct(public Server $server) {}
|
||||
|
|
|
|||
|
|
@ -1,42 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Jobs;
|
||||
|
||||
use App\Models\Team;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldBeEncrypted;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Foundation\Bus\Dispatchable;
|
||||
use Illuminate\Notifications\Messages\MailMessage;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class SubscriptionTrialEndedJob implements ShouldBeEncrypted, ShouldQueue
|
||||
{
|
||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||
|
||||
public function __construct(
|
||||
public Team $team
|
||||
) {}
|
||||
|
||||
public function handle(): void
|
||||
{
|
||||
try {
|
||||
$session = getStripeCustomerPortalSession($this->team);
|
||||
$mail = new MailMessage;
|
||||
$mail->subject('Action required: You trial in Coolify Cloud ended.');
|
||||
$mail->view('emails.trial-ended', [
|
||||
'stripeCustomerPortal' => $session->url,
|
||||
]);
|
||||
$this->team->members()->each(function ($member) use ($mail) {
|
||||
if ($member->isAdmin()) {
|
||||
send_user_an_email($mail, $member->email);
|
||||
send_internal_notification('Trial reminder email sent to '.$member->email);
|
||||
}
|
||||
});
|
||||
} catch (\Throwable $e) {
|
||||
send_internal_notification('SubscriptionTrialEndsSoonJob failed with: '.$e->getMessage());
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,42 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Jobs;
|
||||
|
||||
use App\Models\Team;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldBeEncrypted;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Foundation\Bus\Dispatchable;
|
||||
use Illuminate\Notifications\Messages\MailMessage;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class SubscriptionTrialEndsSoonJob implements ShouldBeEncrypted, ShouldQueue
|
||||
{
|
||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||
|
||||
public function __construct(
|
||||
public Team $team
|
||||
) {}
|
||||
|
||||
public function handle(): void
|
||||
{
|
||||
try {
|
||||
$session = getStripeCustomerPortalSession($this->team);
|
||||
$mail = new MailMessage;
|
||||
$mail->subject('You trial in Coolify Cloud ends soon.');
|
||||
$mail->view('emails.trial-ends-soon', [
|
||||
'stripeCustomerPortal' => $session->url,
|
||||
]);
|
||||
$this->team->members()->each(function ($member) use ($mail) {
|
||||
if ($member->isAdmin()) {
|
||||
send_user_an_email($mail, $member->email);
|
||||
send_internal_notification('Trial reminder email sent to '.$member->email);
|
||||
}
|
||||
});
|
||||
} catch (\Throwable $e) {
|
||||
send_internal_notification('SubscriptionTrialEndsSoonJob failed with: '.$e->getMessage());
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2,8 +2,8 @@
|
|||
|
||||
namespace App\Livewire\Admin;
|
||||
|
||||
use App\Models\Team;
|
||||
use App\Models\User;
|
||||
use Illuminate\Container\Attributes\Auth as AttributesAuth;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
|
|
@ -43,17 +43,13 @@ class Index extends Component
|
|||
|
||||
public function getSubscribers()
|
||||
{
|
||||
$this->inactiveSubscribers = User::whereDoesntHave('teams', function ($query) {
|
||||
$query->whereRelation('subscription', 'stripe_subscription_id', '!=', null);
|
||||
})->count();
|
||||
$this->activeSubscribers = User::whereHas('teams', function ($query) {
|
||||
$query->whereRelation('subscription', 'stripe_subscription_id', '!=', null);
|
||||
})->count();
|
||||
$this->inactiveSubscribers = Team::whereRelation('subscription', 'stripe_invoice_paid', false)->count();
|
||||
$this->activeSubscribers = Team::whereRelation('subscription', 'stripe_invoice_paid', true)->count();
|
||||
}
|
||||
|
||||
public function switchUser(int $user_id)
|
||||
{
|
||||
if (AttributesAuth::id() !== 0) {
|
||||
if (Auth::id() !== 0) {
|
||||
return redirect()->route('dashboard');
|
||||
}
|
||||
$user = User::find($user_id);
|
||||
|
|
|
|||
|
|
@ -66,11 +66,15 @@ class Index extends Component
|
|||
|
||||
public bool $serverReachable = true;
|
||||
|
||||
public ?string $minDockerVersion = null;
|
||||
|
||||
public function mount()
|
||||
{
|
||||
if (auth()->user()?->isMember() && auth()->user()->currentTeam()->show_boarding === true) {
|
||||
return redirect()->route('dashboard');
|
||||
}
|
||||
|
||||
$this->minDockerVersion = str(config('constants.docker.minimum_required_version'))->before('.');
|
||||
$this->privateKeyName = generate_random_name();
|
||||
$this->remoteServerName = generate_random_name();
|
||||
if (isDev()) {
|
||||
|
|
|
|||
|
|
@ -1,37 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Livewire\Dev;
|
||||
|
||||
use Livewire\Component;
|
||||
|
||||
class Compose extends Component
|
||||
{
|
||||
public string $compose = '';
|
||||
|
||||
public string $base64 = '';
|
||||
|
||||
public $services;
|
||||
|
||||
public function mount()
|
||||
{
|
||||
$this->services = get_service_templates();
|
||||
}
|
||||
|
||||
public function setService(string $selected)
|
||||
{
|
||||
$this->base64 = data_get($this->services, $selected.'.compose');
|
||||
if ($this->base64) {
|
||||
$this->compose = base64_decode($this->base64);
|
||||
}
|
||||
}
|
||||
|
||||
public function updatedCompose($value)
|
||||
{
|
||||
$this->base64 = base64_encode($value);
|
||||
}
|
||||
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.dev.compose');
|
||||
}
|
||||
}
|
||||
|
|
@ -91,9 +91,12 @@ class Select extends Component
|
|||
{
|
||||
$services = get_service_templates(true);
|
||||
$services = collect($services)->map(function ($service, $key) {
|
||||
$logo = data_get($service, 'logo', 'svgs/coolify.png');
|
||||
|
||||
return [
|
||||
'name' => str($key)->headline(),
|
||||
'logo' => asset(data_get($service, 'logo', 'svgs/coolify.png')),
|
||||
'logo' => asset($logo),
|
||||
'logo_github_url' => 'https://raw.githubusercontent.com/coollabsio/coolify/refs/heads/main/public/a'.$logo,
|
||||
] + (array) $service;
|
||||
})->all();
|
||||
$gitBasedApplications = [
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ namespace App\Livewire\Server;
|
|||
|
||||
use App\Actions\Proxy\CheckConfiguration;
|
||||
use App\Actions\Proxy\SaveConfiguration;
|
||||
use App\Actions\Proxy\StartProxy;
|
||||
use App\Models\Server;
|
||||
use Livewire\Component;
|
||||
|
||||
|
|
@ -44,14 +43,13 @@ class Proxy extends Component
|
|||
|
||||
public function selectProxy($proxy_type)
|
||||
{
|
||||
$this->server->proxy->set('status', 'exited');
|
||||
$this->server->proxy->set('type', $proxy_type);
|
||||
$this->server->save();
|
||||
$this->selectedProxy = $this->server->proxy->type;
|
||||
if ($this->server->proxySet()) {
|
||||
StartProxy::run($this->server, false);
|
||||
try {
|
||||
$this->server->changeProxy($proxy_type, async: false);
|
||||
$this->selectedProxy = $this->server->proxy->type;
|
||||
$this->dispatch('proxyStatusUpdated');
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
$this->dispatch('proxyStatusUpdated');
|
||||
}
|
||||
|
||||
public function instantSave()
|
||||
|
|
|
|||
|
|
@ -127,7 +127,14 @@ class Show extends Component
|
|||
$this->server->settings->sentinel_custom_url = $this->sentinelCustomUrl;
|
||||
$this->server->settings->is_sentinel_enabled = $this->isSentinelEnabled;
|
||||
$this->server->settings->is_sentinel_debug_enabled = $this->isSentinelDebugEnabled;
|
||||
$this->server->settings->server_timezone = $this->serverTimezone;
|
||||
|
||||
if (! validate_timezone($this->serverTimezone)) {
|
||||
$this->serverTimezone = config('app.timezone');
|
||||
throw new \Exception('Invalid timezone.');
|
||||
} else {
|
||||
$this->server->settings->server_timezone = $this->serverTimezone;
|
||||
}
|
||||
|
||||
$this->server->settings->save();
|
||||
} else {
|
||||
$this->name = $this->server->name;
|
||||
|
|
|
|||
|
|
@ -159,7 +159,8 @@ class ValidateAndInstall extends Component
|
|||
$this->dispatch('refreshBoardingIndex');
|
||||
$this->dispatch('success', 'Server validated.');
|
||||
} else {
|
||||
$this->error = 'Docker Engine version is not 22+. Please install Docker manually before continuing: <a target="_blank" class="underline" href="https://docs.docker.com/engine/install/#server">documentation</a>.';
|
||||
$requiredDockerVersion = str(config('constants.docker.minimum_required_version'))->before('.');
|
||||
$this->error = 'Minimum Docker Engine version '.$requiredDockerVersion.' is not instaled. Please install Docker manually before continuing: <a target="_blank" class="underline" href="https://docs.docker.com/engine/install/#server">documentation</a>.';
|
||||
$this->server->update([
|
||||
'validation_logs' => $this->error,
|
||||
]);
|
||||
|
|
|
|||
|
|
@ -139,6 +139,14 @@ class Index extends Component
|
|||
$error_show = false;
|
||||
$this->server = Server::findOrFail(0);
|
||||
$this->resetErrorBag();
|
||||
|
||||
if (! validate_timezone($this->instance_timezone)) {
|
||||
$this->instance_timezone = config('app.timezone');
|
||||
throw new \Exception('Invalid timezone.');
|
||||
} else {
|
||||
$this->settings->instance_timezone = $this->instance_timezone;
|
||||
}
|
||||
|
||||
if ($this->settings->public_port_min > $this->settings->public_port_max) {
|
||||
$this->addError('settings.public_port_min', 'The minimum port must be lower than the maximum port.');
|
||||
|
||||
|
|
|
|||
|
|
@ -1,58 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Livewire\Settings;
|
||||
|
||||
use App\Actions\License\CheckResaleLicense;
|
||||
use App\Models\InstanceSettings;
|
||||
use Livewire\Component;
|
||||
|
||||
class License extends Component
|
||||
{
|
||||
public InstanceSettings $settings;
|
||||
|
||||
public ?string $instance_id = null;
|
||||
|
||||
protected $rules = [
|
||||
'settings.resale_license' => 'nullable',
|
||||
'settings.is_resale_license_active' => 'nullable',
|
||||
];
|
||||
|
||||
protected $validationAttributes = [
|
||||
'settings.resale_license' => 'License',
|
||||
'instance_id' => 'Instance Id (Do not change this)',
|
||||
'settings.is_resale_license_active' => 'Is License Active',
|
||||
];
|
||||
|
||||
public function mount()
|
||||
{
|
||||
if (! isCloud()) {
|
||||
abort(404);
|
||||
}
|
||||
if (! isInstanceAdmin()) {
|
||||
return redirect()->route('home');
|
||||
}
|
||||
$this->instance_id = config('app.id');
|
||||
$this->settings = instanceSettings();
|
||||
}
|
||||
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.settings.license');
|
||||
}
|
||||
|
||||
public function submit()
|
||||
{
|
||||
$this->validate();
|
||||
$this->settings->save();
|
||||
if ($this->settings->resale_license) {
|
||||
try {
|
||||
CheckResaleLicense::run();
|
||||
$this->dispatch('reloadWindow');
|
||||
} catch (\Throwable $e) {
|
||||
session()->flash('error', 'Something went wrong. Please contact support. <br>Error: '.$e->getMessage());
|
||||
|
||||
return redirect()->route('settings.license');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -14,13 +14,25 @@ class Index extends Component
|
|||
|
||||
public $containers = [];
|
||||
|
||||
public bool $isLoadingContainers = true;
|
||||
|
||||
public function mount()
|
||||
{
|
||||
if (! auth()->user()->isAdmin()) {
|
||||
abort(403);
|
||||
}
|
||||
$this->servers = Server::isReachable()->get();
|
||||
$this->containers = $this->getAllActiveContainers();
|
||||
}
|
||||
|
||||
public function loadContainers()
|
||||
{
|
||||
try {
|
||||
$this->containers = $this->getAllActiveContainers();
|
||||
} catch (\Exception $e) {
|
||||
return handleError($e, $this);
|
||||
} finally {
|
||||
$this->isLoadingContainers = false;
|
||||
}
|
||||
}
|
||||
|
||||
private function getAllActiveContainers()
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ class Index extends Component
|
|||
|
||||
public function mount()
|
||||
{
|
||||
if (config('coolify.waitlist') == false) {
|
||||
if (config('constants.waitlist.enabled') == false) {
|
||||
return redirect()->route('register');
|
||||
}
|
||||
$this->waitingInLine = Waitlist::whereVerified(true)->count();
|
||||
|
|
|
|||
|
|
@ -908,21 +908,7 @@ class Application extends BaseModel
|
|||
|
||||
public function customRepository()
|
||||
{
|
||||
preg_match('/(?<=:)\d+(?=\/)/', $this->git_repository, $matches);
|
||||
$port = 22;
|
||||
if (count($matches) === 1) {
|
||||
$port = $matches[0];
|
||||
$gitHost = str($this->git_repository)->before(':');
|
||||
$gitRepo = str($this->git_repository)->after('/');
|
||||
$repository = "$gitHost:$gitRepo";
|
||||
} else {
|
||||
$repository = $this->git_repository;
|
||||
}
|
||||
|
||||
return [
|
||||
'repository' => $repository,
|
||||
'port' => $port,
|
||||
];
|
||||
return convertGitUrl($this->git_repository, $this->deploymentType(), $this->source);
|
||||
}
|
||||
|
||||
public function generateBaseDir(string $uuid)
|
||||
|
|
@ -955,6 +941,122 @@ class Application extends BaseModel
|
|||
return $git_clone_command;
|
||||
}
|
||||
|
||||
public function getGitRemoteStatus(string $deployment_uuid)
|
||||
{
|
||||
try {
|
||||
['commands' => $lsRemoteCommand] = $this->generateGitLsRemoteCommands(deployment_uuid: $deployment_uuid, exec_in_docker: false);
|
||||
instant_remote_process([$lsRemoteCommand], $this->destination->server, true);
|
||||
|
||||
return [
|
||||
'is_accessible' => true,
|
||||
'error' => null,
|
||||
];
|
||||
} catch (\RuntimeException $ex) {
|
||||
return [
|
||||
'is_accessible' => false,
|
||||
'error' => $ex->getMessage(),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
public function generateGitLsRemoteCommands(string $deployment_uuid, bool $exec_in_docker = true)
|
||||
{
|
||||
$branch = $this->git_branch;
|
||||
['repository' => $customRepository, 'port' => $customPort] = $this->customRepository();
|
||||
$commands = collect([]);
|
||||
$base_command = 'git ls-remote';
|
||||
|
||||
if ($this->deploymentType() === 'source') {
|
||||
$source_html_url = data_get($this, 'source.html_url');
|
||||
$url = parse_url(filter_var($source_html_url, FILTER_SANITIZE_URL));
|
||||
$source_html_url_host = $url['host'];
|
||||
$source_html_url_scheme = $url['scheme'];
|
||||
|
||||
if ($this->source->getMorphClass() == 'App\Models\GithubApp') {
|
||||
if ($this->source->is_public) {
|
||||
$fullRepoUrl = "{$this->source->html_url}/{$customRepository}";
|
||||
$base_command = "{$base_command} {$this->source->html_url}/{$customRepository}";
|
||||
} else {
|
||||
$github_access_token = generate_github_installation_token($this->source);
|
||||
|
||||
if ($exec_in_docker) {
|
||||
$base_command = "{$base_command} $source_html_url_scheme://x-access-token:$github_access_token@$source_html_url_host/{$customRepository}.git";
|
||||
$fullRepoUrl = "$source_html_url_scheme://x-access-token:$github_access_token@$source_html_url_host/{$customRepository}.git";
|
||||
} else {
|
||||
$base_command = "{$base_command} $source_html_url_scheme://x-access-token:$github_access_token@$source_html_url_host/{$customRepository}";
|
||||
$fullRepoUrl = "$source_html_url_scheme://x-access-token:$github_access_token@$source_html_url_host/{$customRepository}";
|
||||
}
|
||||
}
|
||||
|
||||
if ($exec_in_docker) {
|
||||
$commands->push(executeInDocker($deployment_uuid, $base_command));
|
||||
} else {
|
||||
$commands->push($base_command);
|
||||
}
|
||||
|
||||
return [
|
||||
'commands' => $commands->implode(' && '),
|
||||
'branch' => $branch,
|
||||
'fullRepoUrl' => $fullRepoUrl,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->deploymentType() === 'deploy_key') {
|
||||
$fullRepoUrl = $customRepository;
|
||||
$private_key = data_get($this, 'private_key.private_key');
|
||||
if (is_null($private_key)) {
|
||||
throw new RuntimeException('Private key not found. Please add a private key to the application and try again.');
|
||||
}
|
||||
$private_key = base64_encode($private_key);
|
||||
$base_comamnd = "GIT_SSH_COMMAND=\"ssh -o ConnectTimeout=30 -p {$customPort} -o Port={$customPort} -o LogLevel=ERROR -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i /root/.ssh/id_rsa\" {$base_command} {$customRepository}";
|
||||
|
||||
if ($exec_in_docker) {
|
||||
$commands = collect([
|
||||
executeInDocker($deployment_uuid, 'mkdir -p /root/.ssh'),
|
||||
executeInDocker($deployment_uuid, "echo '{$private_key}' | base64 -d | tee /root/.ssh/id_rsa > /dev/null"),
|
||||
executeInDocker($deployment_uuid, 'chmod 600 /root/.ssh/id_rsa'),
|
||||
]);
|
||||
} else {
|
||||
$commands = collect([
|
||||
'mkdir -p /root/.ssh',
|
||||
"echo '{$private_key}' | base64 -d | tee /root/.ssh/id_rsa > /dev/null",
|
||||
'chmod 600 /root/.ssh/id_rsa',
|
||||
]);
|
||||
}
|
||||
|
||||
if ($exec_in_docker) {
|
||||
$commands->push(executeInDocker($deployment_uuid, $base_comamnd));
|
||||
} else {
|
||||
$commands->push($base_comamnd);
|
||||
}
|
||||
|
||||
return [
|
||||
'commands' => $commands->implode(' && '),
|
||||
'branch' => $branch,
|
||||
'fullRepoUrl' => $fullRepoUrl,
|
||||
];
|
||||
}
|
||||
|
||||
if ($this->deploymentType() === 'other') {
|
||||
$fullRepoUrl = $customRepository;
|
||||
$base_command = "{$base_command} {$customRepository}";
|
||||
$base_command = $this->setGitImportSettings($deployment_uuid, $base_command, public: true);
|
||||
|
||||
if ($exec_in_docker) {
|
||||
$commands->push(executeInDocker($deployment_uuid, $base_command));
|
||||
} else {
|
||||
$commands->push($base_command);
|
||||
}
|
||||
|
||||
return [
|
||||
'commands' => $commands->implode(' && '),
|
||||
'branch' => $branch,
|
||||
'fullRepoUrl' => $fullRepoUrl,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
public function generateGitImportCommands(string $deployment_uuid, int $pull_request_id = 0, ?string $git_type = null, bool $exec_in_docker = true, bool $only_checkout = false, ?string $custom_base_dir = null, ?string $commit = null)
|
||||
{
|
||||
$branch = $this->git_branch;
|
||||
|
|
@ -1216,6 +1318,11 @@ class Application extends BaseModel
|
|||
$workdir = rtrim($this->base_directory, '/');
|
||||
$composeFile = $this->docker_compose_location;
|
||||
$fileList = collect([".$workdir$composeFile"]);
|
||||
$gitRemoteStatus = $this->getGitRemoteStatus(deployment_uuid: $uuid);
|
||||
if (! $gitRemoteStatus['is_accessible']) {
|
||||
throw new \RuntimeException("Failed to read Git source:\n\n{$gitRemoteStatus['error']}");
|
||||
}
|
||||
|
||||
$commands = collect([
|
||||
"rm -rf /tmp/{$uuid}",
|
||||
"mkdir -p /tmp/{$uuid}",
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Actions\Proxy\StartProxy;
|
||||
use App\Actions\Server\InstallDocker;
|
||||
use App\Actions\Server\StartSentinel;
|
||||
use App\Enums\ProxyTypes;
|
||||
|
|
@ -26,22 +27,23 @@ use Symfony\Component\Yaml\Yaml;
|
|||
description: 'Server model',
|
||||
type: 'object',
|
||||
properties: [
|
||||
'id' => ['type' => 'integer'],
|
||||
'uuid' => ['type' => 'string'],
|
||||
'name' => ['type' => 'string'],
|
||||
'description' => ['type' => 'string'],
|
||||
'ip' => ['type' => 'string'],
|
||||
'user' => ['type' => 'string'],
|
||||
'port' => ['type' => 'integer'],
|
||||
'proxy' => ['type' => 'object'],
|
||||
'high_disk_usage_notification_sent' => ['type' => 'boolean'],
|
||||
'unreachable_notification_sent' => ['type' => 'boolean'],
|
||||
'unreachable_count' => ['type' => 'integer'],
|
||||
'validation_logs' => ['type' => 'string'],
|
||||
'log_drain_notification_sent' => ['type' => 'boolean'],
|
||||
'swarm_cluster' => ['type' => 'string'],
|
||||
'delete_unused_volumes' => ['type' => 'boolean'],
|
||||
'delete_unused_networks' => ['type' => 'boolean'],
|
||||
'id' => ['type' => 'integer', 'description' => 'The server ID.'],
|
||||
'uuid' => ['type' => 'string', 'description' => 'The server UUID.'],
|
||||
'name' => ['type' => 'string', 'description' => 'The server name.'],
|
||||
'description' => ['type' => 'string', 'description' => 'The server description.'],
|
||||
'ip' => ['type' => 'string', 'description' => 'The IP address.'],
|
||||
'user' => ['type' => 'string', 'description' => 'The user.'],
|
||||
'port' => ['type' => 'integer', 'description' => 'The port number.'],
|
||||
'proxy' => ['type' => 'object', 'description' => 'The proxy configuration.'],
|
||||
'proxy_type' => ['type' => 'string', 'enum' => ['traefik', 'caddy', 'none'], 'description' => 'The proxy type.'],
|
||||
'high_disk_usage_notification_sent' => ['type' => 'boolean', 'description' => 'The flag to indicate if the high disk usage notification has been sent.'],
|
||||
'unreachable_notification_sent' => ['type' => 'boolean', 'description' => 'The flag to indicate if the unreachable notification has been sent.'],
|
||||
'unreachable_count' => ['type' => 'integer', 'description' => 'The unreachable count for your server.'],
|
||||
'validation_logs' => ['type' => 'string', 'description' => 'The validation logs.'],
|
||||
'log_drain_notification_sent' => ['type' => 'boolean', 'description' => 'The flag to indicate if the log drain notification has been sent.'],
|
||||
'swarm_cluster' => ['type' => 'string', 'description' => 'The swarm cluster configuration.'],
|
||||
'delete_unused_volumes' => ['type' => 'boolean', 'description' => 'The flag to indicate if the unused volumes should be deleted.'],
|
||||
'delete_unused_networks' => ['type' => 'boolean', 'description' => 'The flag to indicate if the unused networks should be deleted.'],
|
||||
]
|
||||
)]
|
||||
|
||||
|
|
@ -462,7 +464,7 @@ $schema://$host {
|
|||
|
||||
public function proxyPath()
|
||||
{
|
||||
$base_path = config('coolify.base_config_path');
|
||||
$base_path = config('constants.coolify.base_config_path');
|
||||
$proxyType = $this->proxyType();
|
||||
$proxy_path = "$base_path/proxy";
|
||||
// TODO: should use /traefik for already exisiting configurations?
|
||||
|
|
@ -1251,4 +1253,25 @@ $schema://$host {
|
|||
{
|
||||
return instant_remote_process(['docker restart '.$containerName], $this, false);
|
||||
}
|
||||
|
||||
public function changeProxy(string $proxyType, bool $async = true)
|
||||
{
|
||||
$validProxyTypes = collect(ProxyTypes::cases())->map(function ($proxyType) {
|
||||
return str($proxyType->value)->lower();
|
||||
});
|
||||
if ($validProxyTypes->contains(str($proxyType)->lower())) {
|
||||
$this->proxy->set('type', str($proxyType)->upper());
|
||||
$this->proxy->set('status', 'exited');
|
||||
$this->save();
|
||||
if ($this->proxySet()) {
|
||||
if ($async) {
|
||||
StartProxy::dispatch($this);
|
||||
} else {
|
||||
StartProxy::run($this);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw new \Exception('Invalid proxy type.');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1171,7 +1171,7 @@ class Service extends BaseModel
|
|||
$services = get_service_templates();
|
||||
$service = data_get($services, str($this->name)->beforeLast('-')->value, []);
|
||||
|
||||
return data_get($service, 'documentation', config('constants.docs.base_url'));
|
||||
return data_get($service, 'documentation', config('constants.urls.docs'));
|
||||
}
|
||||
|
||||
public function applications()
|
||||
|
|
|
|||
|
|
@ -172,7 +172,7 @@ class Team extends Model implements SendsDiscord, SendsEmail
|
|||
{
|
||||
return Attribute::make(
|
||||
get: function () {
|
||||
if (config('coolify.self_hosted') || $this->id === 0) {
|
||||
if (config('constants.coolify.self_hosted') || $this->id === 0) {
|
||||
$subscription = 'self-hosted';
|
||||
} else {
|
||||
$subscription = data_get($this, 'subscription');
|
||||
|
|
@ -257,8 +257,15 @@ class Team extends Model implements SendsDiscord, SendsEmail
|
|||
return $this->hasMany(S3Storage::class)->where('is_usable', true);
|
||||
}
|
||||
|
||||
public function trialEnded()
|
||||
public function subscriptionEnded()
|
||||
{
|
||||
$this->subscription->update([
|
||||
'stripe_subscription_id' => null,
|
||||
'stripe_plan_id' => null,
|
||||
'stripe_cancel_at_period_end' => false,
|
||||
'stripe_invoice_paid' => false,
|
||||
'stripe_trial_already_ended' => false,
|
||||
]);
|
||||
foreach ($this->servers as $server) {
|
||||
$server->settings()->update([
|
||||
'is_usable' => false,
|
||||
|
|
@ -267,16 +274,6 @@ class Team extends Model implements SendsDiscord, SendsEmail
|
|||
}
|
||||
}
|
||||
|
||||
public function trialEndedButSubscribed()
|
||||
{
|
||||
foreach ($this->servers as $server) {
|
||||
$server->settings()->update([
|
||||
'is_usable' => true,
|
||||
'is_reachable' => true,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
public function isAnyNotificationEnabled()
|
||||
{
|
||||
if (isCloud()) {
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ class FortifyServiceProvider extends ServiceProvider
|
|||
if (! $settings->is_registration_enabled) {
|
||||
return redirect()->route('login');
|
||||
}
|
||||
if (config('coolify.waitlist')) {
|
||||
if (config('constants.waitlist.enabled')) {
|
||||
return redirect()->route('waitlist.index');
|
||||
} else {
|
||||
return view('auth.register', [
|
||||
|
|
|
|||
|
|
@ -109,7 +109,8 @@ function format_docker_envs_to_json($rawOutput)
|
|||
function checkMinimumDockerEngineVersion($dockerVersion)
|
||||
{
|
||||
$majorDockerVersion = str($dockerVersion)->before('.')->value();
|
||||
if ($majorDockerVersion <= 22) {
|
||||
$requiredDockerVersion = str(config('constants.docker.minimum_required_version'))->before('.')->value();
|
||||
if ($majorDockerVersion < $requiredDockerVersion) {
|
||||
$dockerVersion = null;
|
||||
}
|
||||
|
||||
|
|
@ -225,15 +226,13 @@ function generateServiceSpecificFqdns(ServiceApplication|Application $resource)
|
|||
case $type?->contains('minio'):
|
||||
$MINIO_BROWSER_REDIRECT_URL = $variables->where('key', 'MINIO_BROWSER_REDIRECT_URL')->first();
|
||||
$MINIO_SERVER_URL = $variables->where('key', 'MINIO_SERVER_URL')->first();
|
||||
if (is_null($MINIO_BROWSER_REDIRECT_URL) || is_null($MINIO_SERVER_URL)) {
|
||||
return $payload;
|
||||
}
|
||||
if (is_null($MINIO_BROWSER_REDIRECT_URL?->value)) {
|
||||
|
||||
if (str($MINIO_BROWSER_REDIRECT_URL->value)->isEmpty()) {
|
||||
$MINIO_BROWSER_REDIRECT_URL?->update([
|
||||
'value' => generateFqdn($server, 'console-'.$uuid, true),
|
||||
]);
|
||||
}
|
||||
if (is_null($MINIO_SERVER_URL?->value)) {
|
||||
if (str($MINIO_SERVER_URL->value)->isEmpty()) {
|
||||
$MINIO_SERVER_URL?->update([
|
||||
'value' => generateFqdn($server, 'minio-'.$uuid, true),
|
||||
]);
|
||||
|
|
@ -246,15 +245,13 @@ function generateServiceSpecificFqdns(ServiceApplication|Application $resource)
|
|||
case $type?->contains('logto'):
|
||||
$LOGTO_ENDPOINT = $variables->where('key', 'LOGTO_ENDPOINT')->first();
|
||||
$LOGTO_ADMIN_ENDPOINT = $variables->where('key', 'LOGTO_ADMIN_ENDPOINT')->first();
|
||||
if (is_null($LOGTO_ENDPOINT) || is_null($LOGTO_ADMIN_ENDPOINT)) {
|
||||
return $payload;
|
||||
}
|
||||
if (is_null($LOGTO_ENDPOINT?->value)) {
|
||||
|
||||
if (str($LOGTO_ENDPOINT?->value)->isEmpty()) {
|
||||
$LOGTO_ENDPOINT?->update([
|
||||
'value' => generateFqdn($server, 'logto-'.$uuid),
|
||||
]);
|
||||
}
|
||||
if (is_null($LOGTO_ADMIN_ENDPOINT?->value)) {
|
||||
if (str($LOGTO_ADMIN_ENDPOINT?->value)->isEmpty()) {
|
||||
$LOGTO_ADMIN_ENDPOINT?->update([
|
||||
'value' => generateFqdn($server, 'logto-admin-'.$uuid),
|
||||
]);
|
||||
|
|
@ -397,7 +394,7 @@ function fqdnLabelsForTraefik(string $uuid, Collection $domains, bool $is_force_
|
|||
$middlewares->push('gzip');
|
||||
}
|
||||
if (str($image)->contains('ghost')) {
|
||||
$middlewares->push('redir-ghost');
|
||||
$middlewares->push("redir-ghost-{$uuid}");
|
||||
}
|
||||
if ($redirect_direction === 'non-www' && str($host)->startsWith('www.')) {
|
||||
$labels = $labels->merge($redirect_to_non_www);
|
||||
|
|
@ -420,7 +417,7 @@ function fqdnLabelsForTraefik(string $uuid, Collection $domains, bool $is_force_
|
|||
$middlewares->push('gzip');
|
||||
}
|
||||
if (str($image)->contains('ghost')) {
|
||||
$middlewares->push('redir-ghost');
|
||||
$middlewares->push("redir-ghost-{$uuid}");
|
||||
}
|
||||
if ($redirect_direction === 'non-www' && str($host)->startsWith('www.')) {
|
||||
$labels = $labels->merge($redirect_to_non_www);
|
||||
|
|
@ -469,7 +466,7 @@ function fqdnLabelsForTraefik(string $uuid, Collection $domains, bool $is_force_
|
|||
$middlewares->push('gzip');
|
||||
}
|
||||
if (str($image)->contains('ghost')) {
|
||||
$middlewares->push('redir-ghost');
|
||||
$middlewares->push("redir-ghost-{$uuid}");
|
||||
}
|
||||
if ($redirect_direction === 'non-www' && str($host)->startsWith('www.')) {
|
||||
$labels = $labels->merge($redirect_to_non_www);
|
||||
|
|
@ -492,7 +489,7 @@ function fqdnLabelsForTraefik(string $uuid, Collection $domains, bool $is_force_
|
|||
$middlewares->push('gzip');
|
||||
}
|
||||
if (str($image)->contains('ghost')) {
|
||||
$middlewares->push('redir-ghost');
|
||||
$middlewares->push("redir-ghost-{$uuid}");
|
||||
}
|
||||
if ($redirect_direction === 'non-www' && str($host)->startsWith('www.')) {
|
||||
$labels = $labels->merge($redirect_to_non_www);
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ use App\Models\Application;
|
|||
use App\Models\ApplicationDeploymentQueue;
|
||||
use App\Models\ApplicationPreview;
|
||||
use App\Models\EnvironmentVariable;
|
||||
use App\Models\GithubApp;
|
||||
use App\Models\InstanceSettings;
|
||||
use App\Models\LocalFileVolume;
|
||||
use App\Models\LocalPersistentVolume;
|
||||
|
|
@ -358,7 +359,7 @@ function isDev(): bool
|
|||
|
||||
function isCloud(): bool
|
||||
{
|
||||
return ! config('coolify.self_hosted');
|
||||
return ! config('constants.coolify.self_hosted');
|
||||
}
|
||||
|
||||
function translate_cron_expression($expression_to_validate): string
|
||||
|
|
@ -384,6 +385,11 @@ function validate_cron_expression($expression_to_validate): bool
|
|||
|
||||
return $isValid;
|
||||
}
|
||||
|
||||
function validate_timezone(string $timezone): bool
|
||||
{
|
||||
return in_array($timezone, timezone_identifiers_list());
|
||||
}
|
||||
function send_internal_notification(string $message): void
|
||||
{
|
||||
try {
|
||||
|
|
@ -988,7 +994,7 @@ function generateEnvValue(string $command, Service|Application|null $service = n
|
|||
|
||||
function getRealtime()
|
||||
{
|
||||
$envDefined = env('PUSHER_PORT');
|
||||
$envDefined = config('constants.pusher.port');
|
||||
if (empty($envDefined)) {
|
||||
$url = Url::fromString(Request::getSchemeAndHttpHost());
|
||||
$port = $url->getPort();
|
||||
|
|
@ -4092,3 +4098,53 @@ function defaultNginxConfiguration(): string
|
|||
}
|
||||
}';
|
||||
}
|
||||
|
||||
function convertGitUrl(string $gitRepository, string $deploymentType, ?GithubApp $source = null): array
|
||||
{
|
||||
$repository = $gitRepository;
|
||||
$providerInfo = [
|
||||
'host' => null,
|
||||
'user' => 'git',
|
||||
'port' => 22,
|
||||
'repository' => $gitRepository,
|
||||
];
|
||||
$sshMatches = [];
|
||||
$matches = [];
|
||||
|
||||
// Let's try and parse the string to detect if it's a valid SSH string or not
|
||||
preg_match('/((.*?)\:\/\/)?(.*@.*:.*)/', $gitRepository, $sshMatches);
|
||||
|
||||
if ($deploymentType === 'deploy_key' && empty($sshMatches) && $source) {
|
||||
// If this happens, the user may have provided an HTTP URL when they needed an SSH one
|
||||
// Let's try and fix that for known Git providers
|
||||
switch ($source->getMorphClass()) {
|
||||
case \App\Models\GithubApp::class:
|
||||
$providerInfo['host'] = Url::fromString($source->html_url)->getHost();
|
||||
$providerInfo['port'] = $source->custom_port;
|
||||
$providerInfo['user'] = $source->custom_user;
|
||||
break;
|
||||
}
|
||||
if (! empty($providerInfo['host'])) {
|
||||
// Until we do not support more providers with App (like GithubApp), this will be always true, port will be 22
|
||||
if ($providerInfo['port'] === 22) {
|
||||
$repository = "{$providerInfo['user']}@{$providerInfo['host']}:{$providerInfo['repository']}";
|
||||
} else {
|
||||
$repository = "ssh://{$providerInfo['user']}@{$providerInfo['host']}:{$providerInfo['port']}/{$providerInfo['repository']}";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
preg_match('/(?<=:)\d+(?=\/)/', $gitRepository, $matches);
|
||||
|
||||
if (count($matches) === 1) {
|
||||
$providerInfo['port'] = $matches[0];
|
||||
$gitHost = str($gitRepository)->before(':');
|
||||
$gitRepo = str($gitRepository)->after('/');
|
||||
$repository = "$gitHost:$gitRepo";
|
||||
}
|
||||
|
||||
return [
|
||||
'repository' => $repository,
|
||||
'port' => $providerInfo['port'],
|
||||
];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,14 +12,15 @@
|
|||
],
|
||||
"require": {
|
||||
"php": "^8.2",
|
||||
"3sidedcube/laravel-redoc": "^1.0",
|
||||
"danharrin/livewire-rate-limiting": "^1.1",
|
||||
"doctrine/dbal": "^3.6",
|
||||
"doctrine/dbal": "^4.2",
|
||||
"guzzlehttp/guzzle": "^7.5.0",
|
||||
"laravel/fortify": "^1.16.0",
|
||||
"laravel/framework": "^11",
|
||||
"laravel/framework": "^11.0",
|
||||
"laravel/horizon": "^5.29.1",
|
||||
"laravel/pail": "^1.1",
|
||||
"laravel/prompts": "^0.1.6",
|
||||
"laravel/prompts": "^0.1.18|^0.2.0|^0.3.0",
|
||||
"laravel/sanctum": "^4.0",
|
||||
"laravel/socialite": "^5.14.0",
|
||||
"laravel/tinker": "^2.8.1",
|
||||
|
|
@ -27,7 +28,7 @@
|
|||
"lcobucci/jwt": "^5.0.0",
|
||||
"league/flysystem-aws-s3-v3": "^3.0",
|
||||
"league/flysystem-sftp-v3": "^3.0",
|
||||
"livewire/livewire": "3.4.9",
|
||||
"livewire/livewire": "^3.5",
|
||||
"log1x/laravel-webfonts": "^1.0",
|
||||
"lorisleiva/laravel-actions": "^2.7",
|
||||
"nubs/random-name-generator": "^2.2",
|
||||
|
|
@ -36,17 +37,16 @@
|
|||
"poliander/cron": "^3.0",
|
||||
"purplepixie/phpdns": "^2.1",
|
||||
"pusher/pusher-php-server": "^7.2",
|
||||
"resend/resend-laravel": "^0.13.0",
|
||||
"resend/resend-laravel": "^0.15.0",
|
||||
"sentry/sentry-laravel": "^4.6",
|
||||
"socialiteproviders/microsoft-azure": "^5.1",
|
||||
"spatie/laravel-activitylog": "^4.7.3",
|
||||
"spatie/laravel-data": "^3.4.3",
|
||||
"spatie/laravel-ray": "^1.32.4",
|
||||
"spatie/laravel-data": "^4.11",
|
||||
"spatie/laravel-schemaless-attributes": "^2.4",
|
||||
"spatie/url": "^2.2",
|
||||
"stripe/stripe-php": "^12.0",
|
||||
"symfony/yaml": "^6.2",
|
||||
"visus/cuid2": "^2.0.0",
|
||||
"stripe/stripe-php": "^16.2.0",
|
||||
"symfony/yaml": "^7.1.6",
|
||||
"visus/cuid2": "^4.1.0",
|
||||
"yosymfony/toml": "^1.0",
|
||||
"zircote/swagger-php": "^4.10"
|
||||
},
|
||||
|
|
@ -58,12 +58,13 @@
|
|||
"laravel/telescope": "^5.2",
|
||||
"mockery/mockery": "^1.5.1",
|
||||
"nunomaduro/collision": "^8.1",
|
||||
"pestphp/pest": "^2.16",
|
||||
"phpstan/phpstan": "^1.10",
|
||||
"phpunit/phpunit": "^10.0.19",
|
||||
"serversideup/spin": "^1.1.0",
|
||||
"pestphp/pest": "^3.5",
|
||||
"phpstan/phpstan": "^1.12.10",
|
||||
"phpunit/phpunit": "^11.4",
|
||||
"serversideup/spin": "^2.3",
|
||||
"spatie/laravel-ignition": "^2.1.0",
|
||||
"symfony/http-client": "^6.2"
|
||||
"spatie/laravel-ray": "^1.37",
|
||||
"symfony/http-client": "^7.1"
|
||||
},
|
||||
"minimum-stability": "stable",
|
||||
"prefer-stable": true,
|
||||
|
|
@ -119,4 +120,4 @@
|
|||
"@php artisan key:generate --ansi"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
3552
composer.lock
generated
|
|
@ -1,11 +1,47 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
'docker_install_version' => '26.0',
|
||||
'docs' => [
|
||||
'base_url' => 'https://coolify.io/docs',
|
||||
'coolify' => [
|
||||
'version' => '4.0.0-beta.368',
|
||||
'self_hosted' => env('SELF_HOSTED', true),
|
||||
'autoupdate' => env('AUTOUPDATE', false),
|
||||
'base_config_path' => env('BASE_CONFIG_PATH', '/data/coolify'),
|
||||
'helper_image' => env('HELPER_IMAGE', 'ghcr.io/coollabsio/coolify-helper'),
|
||||
'is_windows_docker_desktop' => env('IS_WINDOWS_DOCKER_DESKTOP', false),
|
||||
],
|
||||
|
||||
'urls' => [
|
||||
'docs' => 'https://coolify.io/docs',
|
||||
'contact' => 'https://coolify.io/docs/contact',
|
||||
],
|
||||
|
||||
'services' => [
|
||||
// Temporary disabled until cache is implemented
|
||||
// 'official' => 'https://cdn.coollabs.io/coolify/service-templates.json',
|
||||
'official' => 'https://raw.githubusercontent.com/coollabsio/coolify/main/templates/service-templates.json',
|
||||
],
|
||||
|
||||
'terminal' => [
|
||||
'protocol' => env('TERMINAL_PROTOCOL'),
|
||||
'host' => env('TERMINAL_HOST'),
|
||||
'port' => env('TERMINAL_PORT'),
|
||||
],
|
||||
|
||||
'pusher' => [
|
||||
'host' => env('PUSHER_HOST'),
|
||||
'port' => env('PUSHER_PORT'),
|
||||
'app_key' => env('PUSHER_APP_KEY'),
|
||||
],
|
||||
|
||||
'horizon' => [
|
||||
'is_horizon_enabled' => env('HORIZON_ENABLED', true),
|
||||
'is_scheduler_enabled' => env('SCHEDULER_ENABLED', true),
|
||||
],
|
||||
|
||||
'docker' => [
|
||||
'minimum_required_version' => '26.0',
|
||||
],
|
||||
|
||||
'ssh' => [
|
||||
'mux_enabled' => env('MUX_ENABLED', env('SSH_MUX_ENABLED', true)),
|
||||
'mux_persist_time' => env('SSH_MUX_PERSIST_TIME', 3600),
|
||||
|
|
@ -13,20 +49,14 @@ return [
|
|||
'server_interval' => 20,
|
||||
'command_timeout' => 7200,
|
||||
],
|
||||
'waitlist' => [
|
||||
'expiration' => 10,
|
||||
],
|
||||
|
||||
'invitation' => [
|
||||
'link' => [
|
||||
'base_url' => '/invitations/',
|
||||
'expiration_days' => 3,
|
||||
],
|
||||
],
|
||||
'services' => [
|
||||
// Temporary disabled until cache is implemented
|
||||
// 'official' => 'https://cdn.coollabs.io/coolify/service-templates.json',
|
||||
'official' => 'https://raw.githubusercontent.com/coollabsio/coolify/main/templates/service-templates.json',
|
||||
],
|
||||
|
||||
'limits' => [
|
||||
'trial_period' => 0,
|
||||
'server' => [
|
||||
|
|
@ -46,4 +76,23 @@ return [
|
|||
'dynamic' => true,
|
||||
],
|
||||
],
|
||||
|
||||
'waitlist' => [
|
||||
'enabled' => env('WAITLIST', false),
|
||||
'expiration' => 10,
|
||||
],
|
||||
|
||||
'sentry' => [
|
||||
'sentry_dsn' => env('SENTRY_DSN'),
|
||||
],
|
||||
|
||||
'webhooks' => [
|
||||
'feedback_discord_webhook' => env('FEEDBACK_DISCORD_WEBHOOK'),
|
||||
'dev_webhook' => env('SERVEO_URL'),
|
||||
],
|
||||
|
||||
'bunny' => [
|
||||
'storage_api_key' => env('BUNNY_STORAGE_API_KEY'),
|
||||
'api_key' => env('BUNNY_API_KEY'),
|
||||
],
|
||||
];
|
||||
|
|
|
|||
|
|
@ -1,17 +0,0 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
'sentry_dsn' => env('SENTRY_DSN'),
|
||||
'docs' => 'https://coolify.io/docs/',
|
||||
'contact' => 'https://coolify.io/docs/contact',
|
||||
'feedback_discord_webhook' => env('FEEDBACK_DISCORD_WEBHOOK'),
|
||||
'self_hosted' => env('SELF_HOSTED', true),
|
||||
'waitlist' => env('WAITLIST', false),
|
||||
'license_url' => 'https://licenses.coollabs.io',
|
||||
'dev_webhook' => env('SERVEO_URL'),
|
||||
'is_windows_docker_desktop' => env('IS_WINDOWS_DOCKER_DESKTOP', false),
|
||||
'base_config_path' => env('BASE_CONFIG_PATH', '/data/coolify'),
|
||||
'helper_image' => env('HELPER_IMAGE', 'ghcr.io/coollabsio/coolify-helper'),
|
||||
'is_horizon_enabled' => env('HORIZON_ENABLED', true),
|
||||
'is_scheduler_enabled' => env('SCHEDULER_ENABLED', true),
|
||||
];
|
||||
28
config/redoc.php
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Directory
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The name of the directory where your OpenAPI definitions are stored.
|
||||
|
|
||||
*/
|
||||
|
||||
'directory' => '',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Variables
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| You can automatically replace variables in your OpenAPI definitions by
|
||||
| adding a key value pair to the array below. This will replace any
|
||||
| instances of :key with the given value.
|
||||
|
|
||||
*/
|
||||
|
||||
'variables' => [],
|
||||
|
||||
];
|
||||
|
|
@ -3,11 +3,11 @@
|
|||
return [
|
||||
|
||||
// @see https://docs.sentry.io/product/sentry-basics/dsn-explainer/
|
||||
'dsn' => config('coolify.sentry_dsn'),
|
||||
'dsn' => config('constants.sentry.sentry_dsn'),
|
||||
|
||||
// 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.367',
|
||||
'release' => config('constants.coolify.version'),
|
||||
|
||||
// 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.367';
|
||||
return '4.0.0-beta.368';
|
||||
|
|
|
|||
|
|
@ -24,9 +24,8 @@ class PopulateSshKeysDirectorySeeder extends Seeder
|
|||
});
|
||||
|
||||
if (isDev()) {
|
||||
$user = env('PUID').':'.env('PGID');
|
||||
Process::run("chown -R $user ".storage_path('app/ssh/keys'));
|
||||
Process::run("chown -R $user ".storage_path('app/ssh/mux'));
|
||||
Process::run('chown -R 9999:9999 '.storage_path('app/ssh/keys'));
|
||||
Process::run('chown -R 9999:9999 '.storage_path('app/ssh/mux'));
|
||||
} else {
|
||||
Process::run('chown -R 9999:root '.storage_path('app/ssh/keys'));
|
||||
Process::run('chown -R 9999:root '.storage_path('app/ssh/mux'));
|
||||
|
|
|
|||
|
|
@ -100,7 +100,7 @@ class ProductionSeeder extends Seeder
|
|||
}
|
||||
}
|
||||
|
||||
if (! isCloud() && config('coolify.is_windows_docker_desktop') == false) {
|
||||
if (! isCloud() && config('constants.coolify.is_windows_docker_desktop') == false) {
|
||||
$coolify_key_name = '@host.docker.internal';
|
||||
$ssh_keys_directory = Storage::disk('ssh-keys')->files();
|
||||
$coolify_key = collect($ssh_keys_directory)->firstWhere(fn ($item) => str($item)->contains($coolify_key_name));
|
||||
|
|
@ -127,7 +127,7 @@ class ProductionSeeder extends Seeder
|
|||
}
|
||||
}
|
||||
}
|
||||
if (config('coolify.is_windows_docker_desktop')) {
|
||||
if (config('constants.coolify.is_windows_docker_desktop')) {
|
||||
PrivateKey::updateOrCreate(
|
||||
[
|
||||
'id' => 0,
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ services:
|
|||
SOKETI_DEFAULT_APP_SECRET: "${PUSHER_APP_SECRET:-coolify}"
|
||||
entrypoint: ["/bin/sh", "/soketi-entrypoint.sh"]
|
||||
vite:
|
||||
image: node:20
|
||||
image: node:20-alpine
|
||||
pull_policy: always
|
||||
working_dir: /var/www/html
|
||||
environment:
|
||||
|
|
@ -74,8 +74,9 @@ services:
|
|||
networks:
|
||||
- coolify
|
||||
testing-host:
|
||||
image: "ghcr.io/coollabsio/coolify-testing-host:latest"
|
||||
pull_policy: always
|
||||
build:
|
||||
context: .
|
||||
dockerfile: ./docker/testing-host/Dockerfile
|
||||
init: true
|
||||
container_name: coolify-testing-host
|
||||
volumes:
|
||||
|
|
@ -88,7 +89,7 @@ services:
|
|||
networks:
|
||||
- coolify
|
||||
mailpit:
|
||||
image: "axllent/mailpit:latest"
|
||||
image: axllent/mailpit:latest
|
||||
pull_policy: always
|
||||
container_name: coolify-mail
|
||||
ports:
|
||||
|
|
|
|||
|
|
@ -86,7 +86,7 @@ services:
|
|||
retries: 10
|
||||
timeout: 2s
|
||||
redis:
|
||||
image: redis:alpine
|
||||
image: redis:7-alpine
|
||||
pull_policy: always
|
||||
container_name: coolify-redis
|
||||
restart: always
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ services:
|
|||
restart: always
|
||||
working_dir: /var/www/html
|
||||
extra_hosts:
|
||||
- 'host.docker.internal:host-gateway'
|
||||
- host.docker.internal:host-gateway
|
||||
networks:
|
||||
- coolify
|
||||
depends_on:
|
||||
|
|
@ -18,7 +18,7 @@ services:
|
|||
networks:
|
||||
- coolify
|
||||
redis:
|
||||
image: redis:alpine
|
||||
image: redis:7-alpine
|
||||
container_name: coolify-redis
|
||||
restart: always
|
||||
networks:
|
||||
|
|
@ -26,7 +26,7 @@ services:
|
|||
soketi:
|
||||
container_name: coolify-realtime
|
||||
extra_hosts:
|
||||
- 'host.docker.internal:host-gateway'
|
||||
- host.docker.internal:host-gateway
|
||||
restart: always
|
||||
networks:
|
||||
- coolify
|
||||
|
|
|
|||
|
|
@ -1,16 +1,29 @@
|
|||
FROM alpine:3.17
|
||||
|
||||
ARG TARGETPLATFORM
|
||||
# Versions
|
||||
# https://hub.docker.com/_/alpine
|
||||
ARG BASE_IMAGE=alpine:3.20
|
||||
# https://download.docker.com/linux/static/stable/
|
||||
ARG DOCKER_VERSION=26.1.3
|
||||
ARG DOCKER_VERSION=27.3.1
|
||||
# https://github.com/docker/compose/releases
|
||||
ARG DOCKER_COMPOSE_VERSION=2.27.1
|
||||
ARG DOCKER_COMPOSE_VERSION=2.30.3
|
||||
# https://github.com/docker/buildx/releases
|
||||
ARG DOCKER_BUILDX_VERSION=0.14.1
|
||||
ARG DOCKER_BUILDX_VERSION=0.18.0
|
||||
# https://github.com/buildpacks/pack/releases
|
||||
ARG PACK_VERSION=0.35.1
|
||||
# https://github.com/railwayapp/nixpacks/releases
|
||||
ARG NIXPACKS_VERSION=1.29.0
|
||||
# https://hub.docker.com/r/minio/mc/tags
|
||||
ARG MINIO_VERSION=RELEASE.2024-03-07T00-31-49Z
|
||||
|
||||
FROM minio/mc:${MINIO_VERSION} AS minio-client
|
||||
|
||||
FROM ${BASE_IMAGE} AS base
|
||||
|
||||
ARG TARGETPLATFORM
|
||||
ARG DOCKER_VERSION
|
||||
ARG DOCKER_COMPOSE_VERSION
|
||||
ARG DOCKER_BUILDX_VERSION
|
||||
ARG PACK_VERSION
|
||||
ARG NIXPACKS_VERSION
|
||||
|
||||
USER root
|
||||
WORKDIR /artifacts
|
||||
|
|
@ -34,9 +47,8 @@ RUN if [[ ${TARGETPLATFORM} == 'linux/arm64' ]]; then \
|
|||
chmod +x ~/.docker/cli-plugins/docker-compose /usr/bin/docker /usr/local/bin/pack /root/.docker/cli-plugins/docker-buildx \
|
||||
;fi
|
||||
|
||||
COPY --from=minio/mc:RELEASE.2024-09-09T07-53-10Z /usr/bin/mc /usr/bin/mc
|
||||
COPY --from=minio-client /usr/bin/mc /usr/bin/mc
|
||||
RUN chmod +x /usr/bin/mc
|
||||
|
||||
ENTRYPOINT ["/sbin/tini", "--"]
|
||||
CMD ["tail", "-f", "/dev/null"]
|
||||
|
||||
|
|
|
|||
8
docker/coolify-realtime/package-lock.json
generated
|
|
@ -7,7 +7,7 @@
|
|||
"dependencies": {
|
||||
"@xterm/addon-fit": "0.10.0",
|
||||
"@xterm/xterm": "5.5.0",
|
||||
"axios": "1.7.5",
|
||||
"axios": "1.7.7",
|
||||
"cookie": "1.0.1",
|
||||
"dotenv": "16.4.5",
|
||||
"node-pty": "1.0.0",
|
||||
|
|
@ -36,9 +36,9 @@
|
|||
"license": "MIT"
|
||||
},
|
||||
"node_modules/axios": {
|
||||
"version": "1.7.5",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-1.7.5.tgz",
|
||||
"integrity": "sha512-fZu86yCo+svH3uqJ/yTdQ0QHpQu5oL+/QE+QPSv6BZSkDAoky9vytxp7u5qk83OJFS3kEBcesWni9WTZAv3tSw==",
|
||||
"version": "1.7.7",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz",
|
||||
"integrity": "sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"follow-redirects": "^1.15.6",
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
"@xterm/addon-fit": "0.10.0",
|
||||
"@xterm/xterm": "5.5.0",
|
||||
"cookie": "1.0.1",
|
||||
"axios": "1.7.5",
|
||||
"axios": "1.7.7",
|
||||
"dotenv": "16.4.5",
|
||||
"node-pty": "1.0.0",
|
||||
"ws": "8.18.0"
|
||||
|
|
|
|||
|
|
@ -1,10 +1,21 @@
|
|||
FROM serversideup/php:8.2-fpm-nginx-v2.2.1
|
||||
# Versions
|
||||
# https://hub.docker.com/r/serversideup/php/tags?name=8.3-fpm-nginx-alpine
|
||||
ARG SERVERSIDEUP_PHP_VERSION=8.2-fpm-nginx-v2.2.1
|
||||
# https://github.com/minio/mc/releases
|
||||
ARG MINIO_VERSION=RELEASE.2024-11-05T11-29-45Z
|
||||
# https://github.com/cloudflare/cloudflared/releases
|
||||
ARG CLOUDFLARED_VERSION=2024.11.0
|
||||
# https://www.postgresql.org/support/versioning/ - Can not updated automatically so keep it at 15
|
||||
ARG POSTGRES_VERSION=15
|
||||
|
||||
FROM minio/mc:${MINIO_VERSION} AS minio-client
|
||||
|
||||
FROM serversideup/php:${SERVERSIDEUP_PHP_VERSION}
|
||||
|
||||
ARG TARGETPLATFORM
|
||||
# https://github.com/cloudflare/cloudflared/releases
|
||||
ARG CLOUDFLARED_VERSION=2024.4.1
|
||||
|
||||
ARG POSTGRES_VERSION=15
|
||||
ARG CLOUDFLARED_VERSION
|
||||
ARG MINIO_VERSION
|
||||
ARG POSTGRES_VERSION
|
||||
|
||||
# Use build arguments for caching
|
||||
ARG BUILDTIME_DEPS="dirmngr ca-certificates software-properties-common gnupg gnupg2 apt-transport-https curl"
|
||||
|
|
@ -41,7 +52,7 @@ RUN --mount=type=cache,target=/root/.cache \
|
|||
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"
|
||||
|
||||
COPY --from=minio/mc:RELEASE.2024-09-09T07-53-10Z /usr/bin/mc /usr/bin/mc
|
||||
COPY --from=minio-client /usr/bin/mc /usr/bin/mc
|
||||
RUN chmod +x /usr/bin/mc
|
||||
|
||||
RUN { \
|
||||
|
|
|
|||
|
|
@ -1,4 +1,15 @@
|
|||
FROM serversideup/php:8.2-fpm-nginx-v2.2.1 AS base
|
||||
# Versions
|
||||
# https://hub.docker.com/r/serversideup/php/tags?name=8.3-fpm-nginx-alpine
|
||||
ARG SERVERSIDEUP_PHP_VERSION=8.2-fpm-nginx-v2.2.1
|
||||
# https://github.com/minio/mc/releases
|
||||
ARG MINIO_VERSION=RELEASE.2024-11-05T11-29-45Z
|
||||
# https://github.com/cloudflare/cloudflared/releases
|
||||
ARG CLOUDFLARED_VERSION=2024.11.0
|
||||
# https://www.postgresql.org/support/versioning/ - Can not updated automatically so keep it at 15
|
||||
ARG POSTGRES_VERSION=15
|
||||
|
||||
|
||||
FROM serversideup/php:${SERVERSIDEUP_PHP_VERSION} AS base
|
||||
WORKDIR /var/www/html
|
||||
|
||||
COPY composer.json composer.lock ./
|
||||
|
|
@ -11,12 +22,13 @@ COPY --from=base --chown=9999:9999 /var/www/html .
|
|||
RUN npm install
|
||||
RUN npm run build
|
||||
|
||||
FROM serversideup/php:8.2-fpm-nginx-v2.2.1
|
||||
FROM minio/mc:${MINIO_VERSION} AS minio-client
|
||||
|
||||
FROM serversideup/php:${SERVERSIDEUP_PHP_VERSION}
|
||||
|
||||
ARG TARGETPLATFORM
|
||||
# https://github.com/cloudflare/cloudflared/releases
|
||||
ARG CLOUDFLARED_VERSION=2024.4.1
|
||||
ARG POSTGRES_VERSION=15
|
||||
ARG CLOUDFLARED_VERSION
|
||||
ARG POSTGRES_VERSION
|
||||
ARG CI=true
|
||||
|
||||
WORKDIR /var/www/html
|
||||
|
|
@ -29,7 +41,7 @@ RUN curl -fSsL https://www.postgresql.org/media/keys/ACCC4CF8.asc | gpg --dearmo
|
|||
RUN echo deb [arch=amd64,arm64,ppc64el signed-by=/usr/share/keyrings/postgresql.gpg] http://apt.postgresql.org/pub/repos/apt/ jammy-pgdg main | tee -a /etc/apt/sources.list.d/postgresql.list
|
||||
|
||||
RUN apt-get update
|
||||
RUN apt-get install postgresql-client-$POSTGRES_VERSION -y
|
||||
RUN apt-get install postgresql-client-${POSTGRES_VERSION} -y
|
||||
|
||||
# Coolify requirements
|
||||
RUN apt-get install -y php8.2-pgsql openssh-client git git-lfs jq lsof vim
|
||||
|
|
@ -47,8 +59,10 @@ COPY --chmod=755 docker/prod/etc/s6-overlay/ /etc/s6-overlay/
|
|||
|
||||
RUN php artisan route:clear
|
||||
RUN php artisan view:clear
|
||||
RUN php artisan config:clear
|
||||
RUN php artisan route:cache
|
||||
RUN php artisan view:cache
|
||||
RUN php artisan config:cache
|
||||
|
||||
RUN echo "alias ll='ls -al'" >>/etc/bash.bashrc
|
||||
RUN echo "alias a='php artisan'" >>/etc/bash.bashrc
|
||||
|
|
@ -71,5 +85,5 @@ RUN { \
|
|||
echo 'post_max_size=256M'; \
|
||||
} > /etc/php/current_version/cli/conf.d/upload-limits.ini
|
||||
|
||||
COPY --from=minio/mc:RELEASE.2024-09-09T07-53-10Z /usr/bin/mc /usr/bin/mc
|
||||
RUN chmod +x /usr/bin/mc
|
||||
COPY --from=minio-client /usr/bin/mc /usr/bin/mc
|
||||
RUN chmod +x /usr/bin/mc
|
||||
|
|
@ -1,16 +1,22 @@
|
|||
# Versions
|
||||
# https://download.docker.com/linux/static/stable/
|
||||
ARG DOCKER_VERSION=27.3.1
|
||||
# https://github.com/docker/compose/releases
|
||||
ARG DOCKER_COMPOSE_VERSION=2.30.3
|
||||
# https://github.com/docker/buildx/releases
|
||||
ARG DOCKER_BUILDX_VERSION=0.18.0
|
||||
|
||||
|
||||
FROM debian:12-slim
|
||||
|
||||
ARG TARGETPLATFORM
|
||||
# https://download.docker.com/linux/static/stable/
|
||||
ARG DOCKER_VERSION=26.1.2
|
||||
# https://github.com/docker/compose/releases
|
||||
ARG DOCKER_COMPOSE_VERSION=2.27.0
|
||||
# https://github.com/docker/buildx/releases
|
||||
ARG DOCKER_BUILDX_VERSION=0.14.0
|
||||
ARG DOCKER_VERSION
|
||||
ARG DOCKER_COMPOSE_VERSION
|
||||
ARG DOCKER_BUILDX_VERSION
|
||||
|
||||
USER root
|
||||
WORKDIR /root
|
||||
ENV PATH "$PATH:/host/usr/local/sbin:/host/usr/local/bin:/host/usr/sbin:/host/usr/bin:/host/sbin:/host/bin"
|
||||
ENV PATH="/host/usr/local/sbin:/host/usr/local/bin:/host/usr/sbin:/host/usr/bin:/host/sbin:/host/bin:$PATH"
|
||||
|
||||
RUN apt update && apt -y install openssh-client openssh-server curl wget git jq jc
|
||||
RUN mkdir -p ~/.docker/cli-plugins
|
||||
|
|
|
|||
|
|
@ -1,23 +0,0 @@
|
|||
# This is an example dynamic configuration.
|
||||
http:
|
||||
routers:
|
||||
catchall:
|
||||
entryPoints:
|
||||
- http
|
||||
- https
|
||||
service: noop
|
||||
rule: HostRegexp(`{catchall:.*}`)
|
||||
priority: 1
|
||||
middlewares:
|
||||
- redirect-regexp
|
||||
services:
|
||||
noop:
|
||||
loadBalancer:
|
||||
servers:
|
||||
- url: ''
|
||||
middlewares:
|
||||
redirect-regexp:
|
||||
redirectRegex:
|
||||
regex: '(.*)'
|
||||
replacement: 'https://coolify.io'
|
||||
permanent: false
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
# This is an example dynamic configuration.
|
||||
http:
|
||||
routers:
|
||||
coolify-http:
|
||||
entryPoints:
|
||||
- http
|
||||
service: coolify
|
||||
rule: Host(`coolify.io`)
|
||||
services:
|
||||
coolify:
|
||||
loadBalancer:
|
||||
servers:
|
||||
-
|
||||
url: 'http://coolify:80'
|
||||
7985
openapi.json
Normal file
50
openapi.yaml
|
|
@ -1,4 +1,4 @@
|
|||
openapi: 3.0.0
|
||||
openapi: 3.1.0
|
||||
info:
|
||||
title: Coolify
|
||||
version: '0.1'
|
||||
|
|
@ -3311,7 +3311,7 @@ paths:
|
|||
type: string
|
||||
responses:
|
||||
'200':
|
||||
description: 'Project details'
|
||||
description: 'Environment details'
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
|
|
@ -3467,9 +3467,7 @@ paths:
|
|||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/PrivateKey'
|
||||
$ref: '#/components/schemas/PrivateKey'
|
||||
'401':
|
||||
$ref: '#/components/responses/401'
|
||||
'400':
|
||||
|
|
@ -3579,6 +3577,11 @@ paths:
|
|||
type: boolean
|
||||
example: false
|
||||
description: 'Instant validate.'
|
||||
proxy_type:
|
||||
type: string
|
||||
enum: [traefik, caddy, none]
|
||||
example: traefik
|
||||
description: 'The proxy type.'
|
||||
type: object
|
||||
responses:
|
||||
'201':
|
||||
|
|
@ -3699,6 +3702,10 @@ paths:
|
|||
instant_validate:
|
||||
type: boolean
|
||||
description: 'Instant validate.'
|
||||
proxy_type:
|
||||
type: string
|
||||
enum: [traefik, caddy, none]
|
||||
description: 'The proxy type.'
|
||||
type: object
|
||||
responses:
|
||||
'201':
|
||||
|
|
@ -4759,6 +4766,10 @@ components:
|
|||
compose_parsing_version:
|
||||
type: string
|
||||
description: 'How Coolify parse the compose file.'
|
||||
custom_nginx_configuration:
|
||||
type: string
|
||||
nullable: true
|
||||
description: 'Custom Nginx configuration base64 encoded.'
|
||||
type: object
|
||||
ApplicationDeploymentQueue:
|
||||
description: 'Project model'
|
||||
|
|
@ -4909,36 +4920,59 @@ components:
|
|||
properties:
|
||||
id:
|
||||
type: integer
|
||||
description: 'The server ID.'
|
||||
uuid:
|
||||
type: string
|
||||
description: 'The server UUID.'
|
||||
name:
|
||||
type: string
|
||||
description: 'The server name.'
|
||||
description:
|
||||
type: string
|
||||
description: 'The server description.'
|
||||
ip:
|
||||
type: string
|
||||
description: 'The IP address.'
|
||||
user:
|
||||
type: string
|
||||
description: 'The user.'
|
||||
port:
|
||||
type: integer
|
||||
description: 'The port number.'
|
||||
proxy:
|
||||
type: object
|
||||
description: 'The proxy configuration.'
|
||||
proxy_type:
|
||||
type: string
|
||||
enum:
|
||||
- traefik
|
||||
- caddy
|
||||
- none
|
||||
description: 'The proxy type.'
|
||||
high_disk_usage_notification_sent:
|
||||
type: boolean
|
||||
description: 'The flag to indicate if the high disk usage notification has been sent.'
|
||||
unreachable_notification_sent:
|
||||
type: boolean
|
||||
description: 'The flag to indicate if the unreachable notification has been sent.'
|
||||
unreachable_count:
|
||||
type: integer
|
||||
description: 'The unreachable count for your server.'
|
||||
validation_logs:
|
||||
type: string
|
||||
description: 'The validation logs.'
|
||||
log_drain_notification_sent:
|
||||
type: boolean
|
||||
description: 'The flag to indicate if the log drain notification has been sent.'
|
||||
swarm_cluster:
|
||||
type: string
|
||||
description: 'The swarm cluster configuration.'
|
||||
delete_unused_volumes:
|
||||
type: boolean
|
||||
description: 'The flag to indicate if the unused volumes should be deleted.'
|
||||
delete_unused_networks:
|
||||
type: boolean
|
||||
description: 'The flag to indicate if the unused networks should be deleted.'
|
||||
type: object
|
||||
ServerSetting:
|
||||
description: 'Server Settings model'
|
||||
|
|
@ -5136,6 +5170,9 @@ components:
|
|||
smtp_notifications_database_backups:
|
||||
type: boolean
|
||||
description: 'Whether to send database backup notifications via SMTP.'
|
||||
smtp_notifications_server_disk_usage:
|
||||
type: boolean
|
||||
description: 'Whether to send server disk usage notifications via SMTP.'
|
||||
discord_enabled:
|
||||
type: boolean
|
||||
description: 'Whether Discord is enabled or not.'
|
||||
|
|
@ -5157,6 +5194,9 @@ components:
|
|||
discord_notifications_scheduled_tasks:
|
||||
type: boolean
|
||||
description: 'Whether to send scheduled task notifications via Discord.'
|
||||
discord_notifications_server_disk_usage:
|
||||
type: boolean
|
||||
description: 'Whether to send server disk usage notifications via Discord.'
|
||||
show_boarding:
|
||||
type: boolean
|
||||
description: 'Whether to show the boarding screen or not.'
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ CDN="https://cdn.coollabs.io/coolify-nightly"
|
|||
DATE=$(date +"%Y%m%d-%H%M%S")
|
||||
|
||||
VERSION="1.6"
|
||||
DOCKER_VERSION="26.0"
|
||||
DOCKER_VERSION="27.3"
|
||||
# TODO: Ask for a user
|
||||
CURRENT_USER=$USER
|
||||
|
||||
|
|
|
|||
1084
package-lock.json
generated
35
package.json
|
|
@ -1,4 +1,5 @@
|
|||
{
|
||||
"name": "coolify",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
|
|
@ -6,28 +7,24 @@
|
|||
"build": "vite build"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vitejs/plugin-vue": "4.5.1",
|
||||
"autoprefixer": "10.4.19",
|
||||
"axios": "1.7.5",
|
||||
"laravel-echo": "1.16.1",
|
||||
"laravel-vite-plugin": "0.8.1",
|
||||
"postcss": "8.4.38",
|
||||
"@vitejs/plugin-vue": "5.2.0",
|
||||
"autoprefixer": "10.4.20",
|
||||
"axios": "1.7.7",
|
||||
"laravel-echo": "1.17.0",
|
||||
"laravel-vite-plugin": "1.0.6",
|
||||
"postcss": "8.4.49",
|
||||
"pusher-js": "8.4.0-rc2",
|
||||
"tailwindcss": "3.4.4",
|
||||
"vite": "4.5.5",
|
||||
"vue": "3.4.29"
|
||||
"tailwind-scrollbar": "^3.1.0",
|
||||
"tailwindcss": "3.4.14",
|
||||
"vite": "5.4.11",
|
||||
"vue": "3.5.12"
|
||||
},
|
||||
"dependencies": {
|
||||
"@tailwindcss/forms": "0.5.7",
|
||||
"@tailwindcss/typography": "0.5.13",
|
||||
"@tailwindcss/forms": "0.5.9",
|
||||
"@tailwindcss/typography": "0.5.15",
|
||||
"@xterm/addon-fit": "^0.10.0",
|
||||
"@xterm/xterm": "^5.5.0",
|
||||
"alpinejs": "3.14.0",
|
||||
"cookie": "^0.7.0",
|
||||
"dotenv": "^16.4.5",
|
||||
"ioredis": "5.4.1",
|
||||
"node-pty": "^1.0.0",
|
||||
"tailwindcss-scrollbar": "0.1.0",
|
||||
"ws": "^8.17.0"
|
||||
"alpinejs": "3.14.3",
|
||||
"ioredis": "5.4.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,21 +0,0 @@
|
|||
<IfModule mod_rewrite.c>
|
||||
<IfModule mod_negotiation.c>
|
||||
Options -MultiViews -Indexes
|
||||
</IfModule>
|
||||
|
||||
RewriteEngine On
|
||||
|
||||
# Handle Authorization Header
|
||||
RewriteCond %{HTTP:Authorization} .
|
||||
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
|
||||
|
||||
# Redirect Trailing Slashes If Not A Folder...
|
||||
RewriteCond %{REQUEST_FILENAME} !-d
|
||||
RewriteCond %{REQUEST_URI} (.+)/$
|
||||
RewriteRule ^ %1 [L,R=301]
|
||||
|
||||
# Send Requests To Front Controller...
|
||||
RewriteCond %{REQUEST_FILENAME} !-d
|
||||
RewriteCond %{REQUEST_FILENAME} !-f
|
||||
RewriteRule ^ index.php [L]
|
||||
</IfModule>
|
||||
BIN
public/svgs/apprise.png
Normal file
|
After Width: | Height: | Size: 157 KiB |
BIN
public/svgs/cyberchef.jpeg
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
public/svgs/dashy.png
Normal file
|
After Width: | Height: | Size: 58 KiB |
BIN
public/svgs/faraday.png
Normal file
|
After Width: | Height: | Size: 3.9 KiB |
1
public/svgs/firefox.svg
Normal file
|
After Width: | Height: | Size: 11 KiB |
1
public/svgs/hoarder.svg
Normal file
|
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2" viewBox="0 0 355 354" height="24" class="fill-foreground"><path d="M565.33 118.79H253.02c-11.56 0-20.93 9.37-20.93 20.93v310.72c0 11.56 9.37 20.93 20.93 20.93h312.31c11.56 0 20.93-9.37 20.93-20.93V139.72c0-11.56-9.37-20.93-20.93-20.93M386.85 419.57c0 3.01-2.45 5.46-5.46 5.46h-96.28c-3.01 0-5.46-2.45-5.46-5.46V169.43c0-3.01 2.45-5.47 5.46-5.47h94.76a5.47 5.47 0 0 1 5.46 5.47v95.21s-.52 40.97 1.52 73.12v81.82zm150.34 0c0 4.35-4.83 6.95-8.44 4.57l-43.9-28.7c-1.9-1.26-4.35-1.19-6.21.15l-38.48 27.81c-1.6 1.19-3.49 1.26-5.09.67-1.41-1-2.34-2.64-2.34-4.5V225.34c5.21-1 11-1.56 17.7-1.56 32.86 0 86.77 18.59 86.77 71v124.8z" style="fill-rule:nonzero" transform="translate(-232 -118)"></path></svg>
|
||||
|
After Width: | Height: | Size: 842 B |
BIN
public/svgs/hoppscotch.png
Normal file
|
After Width: | Height: | Size: 130 KiB |
90
public/svgs/jupyter.svg
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
<svg width="44" height="51" viewBox="0 0 44 51" version="2.0" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:figma="http://www.figma.com/figma/ns">
|
||||
<title>Group.svg</title>
|
||||
<desc>Created using Figma 0.90</desc>
|
||||
<g id="Canvas" transform="translate(-1640 -2453)" figma:type="canvas">
|
||||
<g id="Group" style="mix-blend-mode:normal;" figma:type="group">
|
||||
<g id="Group" style="mix-blend-mode:normal;" figma:type="group">
|
||||
<g id="Group" style="mix-blend-mode:normal;" figma:type="group">
|
||||
<g id="g" style="mix-blend-mode:normal;" figma:type="group">
|
||||
<g id="path" style="mix-blend-mode:normal;" figma:type="group">
|
||||
<g id="path9 fill" style="mix-blend-mode:normal;" figma:type="vector">
|
||||
<use xlink:href="#path0_fill" transform="translate(1640.54 2474.36)" fill="#4E4E4E" style="mix-blend-mode:normal;"/>
|
||||
</g>
|
||||
</g>
|
||||
<g id="path" style="mix-blend-mode:normal;" figma:type="group">
|
||||
<g id="path10 fill" style="mix-blend-mode:normal;" figma:type="vector">
|
||||
<use xlink:href="#path1_fill" transform="translate(1645.68 2474.37)" fill="#4E4E4E" style="mix-blend-mode:normal;"/>
|
||||
</g>
|
||||
</g>
|
||||
<g id="path" style="mix-blend-mode:normal;" figma:type="group">
|
||||
<g id="path11 fill" style="mix-blend-mode:normal;" figma:type="vector">
|
||||
<use xlink:href="#path2_fill" transform="translate(1653.39 2474.26)" fill="#4E4E4E" style="mix-blend-mode:normal;"/>
|
||||
</g>
|
||||
</g>
|
||||
<g id="path" style="mix-blend-mode:normal;" figma:type="group">
|
||||
<g id="path12 fill" style="mix-blend-mode:normal;" figma:type="vector">
|
||||
<use xlink:href="#path3_fill" transform="translate(1660.43 2474.39)" fill="#4E4E4E" style="mix-blend-mode:normal;"/>
|
||||
</g>
|
||||
</g>
|
||||
<g id="path" style="mix-blend-mode:normal;" figma:type="group">
|
||||
<g id="path13 fill" style="mix-blend-mode:normal;" figma:type="vector">
|
||||
<use xlink:href="#path4_fill" transform="translate(1667.55 2472.54)" fill="#4E4E4E" style="mix-blend-mode:normal;"/>
|
||||
</g>
|
||||
</g>
|
||||
<g id="path" style="mix-blend-mode:normal;" figma:type="group">
|
||||
<g id="path14 fill" style="mix-blend-mode:normal;" figma:type="vector">
|
||||
<use xlink:href="#path5_fill" transform="translate(1672.47 2474.29)" fill="#4E4E4E" style="mix-blend-mode:normal;"/>
|
||||
</g>
|
||||
</g>
|
||||
<g id="path" style="mix-blend-mode:normal;" figma:type="group">
|
||||
<g id="path15 fill" style="mix-blend-mode:normal;" figma:type="vector">
|
||||
<use xlink:href="#path6_fill" transform="translate(1679.98 2474.24)" fill="#4E4E4E" style="mix-blend-mode:normal;"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="g" style="mix-blend-mode:normal;" figma:type="group">
|
||||
<g id="path" style="mix-blend-mode:normal;" figma:type="group">
|
||||
<g id="path16 fill" style="mix-blend-mode:normal;" figma:type="vector">
|
||||
<use xlink:href="#path7_fill" transform="translate(1673.48 2453.69)" fill="#767677" style="mix-blend-mode:normal;"/>
|
||||
</g>
|
||||
</g>
|
||||
<g id="path" style="mix-blend-mode:normal;" figma:type="group">
|
||||
<g id="path17 fill" style="mix-blend-mode:normal;" figma:type="vector">
|
||||
<use xlink:href="#path8_fill" transform="translate(1643.21 2484.27)" fill="#F37726" style="mix-blend-mode:normal;"/>
|
||||
</g>
|
||||
</g>
|
||||
<g id="path" style="mix-blend-mode:normal;" figma:type="group">
|
||||
<g id="path18 fill" style="mix-blend-mode:normal;" figma:type="vector">
|
||||
<use xlink:href="#path9_fill" transform="translate(1643.21 2457.88)" fill="#F37726" style="mix-blend-mode:normal;"/>
|
||||
</g>
|
||||
</g>
|
||||
<g id="path" style="mix-blend-mode:normal;" figma:type="group">
|
||||
<g id="path19 fill" style="mix-blend-mode:normal;" figma:type="vector">
|
||||
<use xlink:href="#path10_fill" transform="translate(1643.28 2496.09)" fill="#9E9E9E" style="mix-blend-mode:normal;"/>
|
||||
</g>
|
||||
</g>
|
||||
<g id="path" style="mix-blend-mode:normal;" figma:type="group">
|
||||
<g id="path20 fill" style="mix-blend-mode:normal;" figma:type="vector">
|
||||
<use xlink:href="#path11_fill" transform="translate(1641.87 2458.43)" fill="#616262" style="mix-blend-mode:normal;"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<defs>
|
||||
<path id="path0_fill" d="M 1.74498 5.47533C 1.74498 7.03335 1.62034 7.54082 1.29983 7.91474C 0.943119 8.23595 0.480024 8.41358 0 8.41331L 0.124642 9.3036C 0.86884 9.31366 1.59095 9.05078 2.15452 8.56466C 2.45775 8.19487 2.6834 7.76781 2.818 7.30893C 2.95261 6.85005 2.99341 6.36876 2.93798 5.89377L 2.93798 0L 1.74498 0L 1.74498 5.43972L 1.74498 5.47533Z"/>
|
||||
<path id="path1_fill" d="M 5.50204 4.76309C 5.50204 5.43081 5.50204 6.02731 5.55545 6.54368L 4.496 6.54368L 4.42478 5.48423C 4.20318 5.85909 3.88627 6.16858 3.50628 6.38125C 3.12628 6.59392 2.69675 6.70219 2.26135 6.69503C 1.22861 6.69503 0 6.13415 0 3.84608L 0 0.0445149L 1.193 0.0445149L 1.193 3.6057C 1.193 4.84322 1.57583 5.67119 2.65309 5.67119C 2.87472 5.67358 3.09459 5.63168 3.29982 5.54796C 3.50505 5.46424 3.69149 5.34039 3.84822 5.18366C 4.00494 5.02694 4.1288 4.84049 4.21252 4.63527C 4.29623 4.43004 4.33813 4.21016 4.33575 3.98853L 4.33575 0L 5.52874 0L 5.52874 4.72748L 5.50204 4.76309Z"/>
|
||||
<path id="path2_fill" d="M 0.0534178 2.27264C 0.0534178 1.44466 0.0534178 0.768036 0 0.153731L 1.06836 0.153731L 1.12177 1.2666C 1.3598 0.864535 1.70247 0.534594 2.11325 0.311954C 2.52404 0.0893145 2.98754 -0.0176786 3.45435 0.00238095C 5.03908 0.00238095 6.23208 1.32892 6.23208 3.30538C 6.23208 5.63796 4.7987 6.79535 3.24958 6.79535C 2.85309 6.81304 2.45874 6.7281 2.10469 6.54874C 1.75064 6.36937 1.44888 6.10166 1.22861 5.77151L 1.22861 5.77151L 1.22861 9.33269L 0.0534178 9.33269L 0.0534178 2.29935L 0.0534178 2.27264ZM 1.22861 4.00872C 1.23184 4.17026 1.24972 4.33117 1.28203 4.48948C 1.38304 4.88479 1.61299 5.23513 1.93548 5.48506C 2.25798 5.735 2.65461 5.87026 3.06262 5.86944C 4.31794 5.86944 5.05689 4.8456 5.05689 3.3588C 5.05689 2.05897 4.36246 0.946096 3.10714 0.946096C 2.61036 0.986777 2.14548 1.20726 1.79965 1.5662C 1.45382 1.92514 1.25079 2.3979 1.22861 2.89585L 1.22861 4.00872Z"/>
|
||||
<path id="path3_fill" d="M 1.31764 0.0178059L 2.75102 3.85499C 2.90237 4.28233 3.06262 4.7987 3.16946 5.18153C 3.2941 4.7898 3.42764 4.29123 3.5879 3.82828L 4.88773 0.0178059L 6.14305 0.0178059L 4.36246 4.64735C 3.47216 6.87309 2.92908 8.02158 2.11 8.71601C 1.69745 9.09283 1.19448 9.35658 0.649917 9.48166L 0.356119 8.48453C 0.736886 8.35942 1.09038 8.16304 1.39777 7.90584C 1.8321 7.55188 2.17678 7.10044 2.4038 6.5882C 2.45239 6.49949 2.48551 6.40314 2.50173 6.3033C 2.49161 6.19586 2.46457 6.0907 2.42161 5.9917L 0 0L 1.29983 0L 1.31764 0.0178059Z"/>
|
||||
<path id="path4_fill" d="M 2.19013 0L 2.19013 1.86962L 3.8995 1.86962L 3.8995 2.75992L 2.19013 2.75992L 2.19013 6.26769C 2.19013 7.06896 2.42161 7.53191 3.08043 7.53191C 3.31442 7.53574 3.54789 7.5088 3.77486 7.45179L 3.82828 8.34208C 3.48794 8.45999 3.12881 8.51431 2.76882 8.50234C 2.53042 8.51726 2.29161 8.48043 2.06878 8.39437C 1.84595 8.30831 1.64438 8.17506 1.47789 8.00377C 1.11525 7.51873 0.949826 6.91431 1.01494 6.31221L 1.01494 2.75102L 0 2.75102L 0 1.86072L 1.03274 1.86072L 1.03274 0.275992L 2.19013 0Z"/>
|
||||
<path id="path5_fill" d="M 1.17716 3.57899C 1.153 3.88093 1.19468 4.18451 1.29933 4.46876C 1.40398 4.75301 1.5691 5.01114 1.78329 5.22532C 1.99747 5.43951 2.2556 5.60463 2.53985 5.70928C 2.8241 5.81393 3.12768 5.85561 3.42962 5.83145C 4.04033 5.84511 4.64706 5.72983 5.21021 5.49313L 5.41498 6.38343C 4.72393 6.66809 3.98085 6.80458 3.23375 6.78406C 2.79821 6.81388 2.36138 6.74914 1.95322 6.59427C 1.54505 6.43941 1.17522 6.19809 0.869071 5.88688C 0.562928 5.57566 0.327723 5.2019 0.179591 4.79125C 0.0314584 4.38059 -0.0260962 3.94276 0.0108748 3.50777C 0.0108748 1.54912 1.17716 0 3.0824 0C 5.21911 0 5.75329 1.86962 5.75329 3.06262C 5.76471 3.24644 5.76471 3.43079 5.75329 3.61461L 1.15046 3.61461L 1.17716 3.57899ZM 4.66713 2.6887C 4.70149 2.45067 4.68443 2.20805 4.61709 1.97718C 4.54976 1.74631 4.43372 1.53255 4.2768 1.35031C 4.11987 1.16808 3.92571 1.0216 3.70739 0.920744C 3.48907 0.81989 3.25166 0.767006 3.01118 0.765656C 2.52201 0.801064 2.06371 1.01788 1.72609 1.37362C 1.38847 1.72935 1.19588 2.19835 1.18607 2.6887L 4.66713 2.6887Z"/>
|
||||
<path id="path6_fill" d="M 0.0534178 2.19228C 0.0534178 1.42663 0.0534178 0.767806 0 0.162404L 1.06836 0.162404L 1.06836 1.43553L 1.12177 1.43553C 1.23391 1.04259 1.4656 0.694314 1.78468 0.439049C 2.10376 0.183783 2.4944 0.034196 2.90237 0.0110538C 3.01466 -0.00368459 3.12839 -0.00368459 3.24068 0.0110538L 3.24068 1.12393C 3.10462 1.10817 2.9672 1.10817 2.83114 1.12393C 2.427 1.13958 2.04237 1.30182 1.7491 1.58035C 1.45583 1.85887 1.27398 2.23462 1.23751 2.63743C 1.20422 2.8196 1.18635 3.00425 1.1841 3.18941L 1.1841 6.65267L 0.00890297 6.65267L 0.00890297 2.20118L 0.0534178 2.19228Z"/>
|
||||
<path id="path7_fill" d="M 6.03059 2.83565C 6.06715 3.43376 5.92485 4.02921 5.6218 4.54615C 5.31875 5.0631 4.86869 5.47813 4.32893 5.73839C 3.78917 5.99864 3.18416 6.09233 2.59097 6.00753C 1.99778 5.92272 1.44326 5.66326 0.998048 5.26219C 0.552837 4.86113 0.23709 4.33661 0.0910307 3.75546C -0.0550287 3.17431 -0.0247891 2.56283 0.177897 1.99893C 0.380583 1.43503 0.746541 0.944221 1.22915 0.589037C 1.71176 0.233853 2.28918 0.0303686 2.88784 0.00450543C 3.28035 -0.0170932 3.67326 0.0391144 4.04396 0.169896C 4.41467 0.300677 4.75587 0.503453 5.04794 0.766561C 5.34 1.02967 5.57718 1.34792 5.74582 1.70301C 5.91446 2.0581 6.01124 2.44303 6.03059 2.83565L 6.03059 2.83565Z"/>
|
||||
<path id="path8_fill" d="M 18.6962 7.12238C 10.6836 7.12238 3.64131 4.24672 0 0C 1.41284 3.82041 3.96215 7.1163 7.30479 9.44404C 10.6474 11.7718 14.623 13.0196 18.6962 13.0196C 22.7695 13.0196 26.745 11.7718 30.0877 9.44404C 33.4303 7.1163 35.9796 3.82041 37.3925 4.0486e-13C 33.7601 4.24672 26.7445 7.12238 18.6962 7.12238Z"/>
|
||||
<path id="path9_fill" d="M 18.6962 5.89725C 26.7089 5.89725 33.7512 8.77291 37.3925 13.0196C 35.9796 9.19922 33.4303 5.90333 30.0877 3.57559C 26.745 1.24785 22.7695 4.0486e-13 18.6962 0C 14.623 4.0486e-13 10.6474 1.24785 7.30479 3.57559C 3.96215 5.90333 1.41284 9.19922 0 13.0196C 3.64131 8.76401 10.648 5.89725 18.6962 5.89725Z"/>
|
||||
<path id="path10_fill" d="M 7.59576 3.56656C 7.64276 4.31992 7.46442 5.07022 7.08347 5.72186C 6.70251 6.3735 6.13619 6.89698 5.45666 7.22561C 4.77713 7.55424 4.01515 7.67314 3.26781 7.56716C 2.52046 7.46117 1.82158 7.13511 1.26021 6.63051C 0.698839 6.12591 0.300394 5.46561 0.115637 4.73375C -0.0691191 4.00188 -0.0318219 3.23159 0.222777 2.52099C 0.477376 1.8104 0.93775 1.19169 1.54524 0.743685C 2.15274 0.295678 2.87985 0.0386595 3.63394 0.00537589C 4.12793 -0.0210471 4.62229 0.0501173 5.08878 0.214803C 5.55526 0.37949 5.98473 0.63447 6.35264 0.965179C 6.72055 1.29589 7.01971 1.69584 7.233 2.1422C 7.4463 2.58855 7.56957 3.07256 7.59576 3.56656L 7.59576 3.56656Z"/>
|
||||
<path id="path11_fill" d="M 2.25061 4.37943C 1.81886 4.39135 1.39322 4.27535 1.02722 4.04602C 0.661224 3.81668 0.371206 3.48424 0.193641 3.09052C 0.0160762 2.69679 -0.0411078 2.25935 0.0292804 1.83321C 0.0996686 1.40707 0.294486 1.01125 0.589233 0.695542C 0.883981 0.37983 1.2655 0.158316 1.68581 0.0588577C 2.10611 -0.0406005 2.54644 -0.0135622 2.95143 0.136572C 3.35641 0.286707 3.70796 0.553234 3.96186 0.902636C 4.21577 1.25204 4.3607 1.66872 4.37842 2.10027C 4.39529 2.6838 4.18131 3.25044 3.78293 3.67715C 3.38455 4.10387 2.83392 4.35623 2.25061 4.37943Z"/>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 16 KiB |
1
public/svgs/mosquitto.svg
Normal file
|
|
@ -0,0 +1 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <!-- Created with Inkscape (http://www.inkscape.org/) --> <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" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" id="svg4136" version="1.1" inkscape:version="0.91 r13725" xml:space="preserve" width="278.23288" height="278.23288" viewBox="0 0 278.23288 278.23288" sodipodi:docname="mosquitto-logo-only.svg"><metadata id="metadata4142"><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><defs id="defs4140" /><sodipodi:namedview pagecolor="#ffffff" bordercolor="#666666" borderopacity="1" objecttolerance="10" gridtolerance="10" guidetolerance="10" inkscape:pageopacity="0" inkscape:pageshadow="2" inkscape:window-width="1280" inkscape:window-height="995" id="namedview4138" showgrid="false" inkscape:zoom="1.7899063" inkscape:cx="67.324802" inkscape:cy="84.142768" inkscape:window-x="1280" inkscape:window-y="0" inkscape:window-maximized="1" inkscape:current-layer="g4144" fit-margin-top="0" fit-margin-left="0" fit-margin-right="0" fit-margin-bottom="0" /><g id="g4144" inkscape:groupmode="layer" inkscape:label="mosquitto" transform="matrix(1.25,0,0,-1.25,-387.06488,575.71439)"><g id="g3377" transform="translate(0,26.44071)"><path inkscape:connector-curvature="0" id="path4160" style="fill:#f3771c;fill-opacity:1;fill-rule:evenodd;stroke:none" d="m 420.9449,237.9852 3.1034,42.3947 2.5194,34.4248 c 5.1916,2.194 8.8356,7.3344 8.8356,13.324 0,7.9837 -6.4746,14.4584 -14.4584,14.4584 -7.9838,0 -14.4584,-6.4747 -14.4584,-14.4584 0,-5.9896 3.6439,-11.13 8.8356,-13.324 l 2.5194,-34.4248 3.1034,-42.3947 z" /><path inkscape:connector-curvature="0" id="path4162" style="fill:#3c5280;fill-opacity:1;fill-rule:evenodd;stroke:none" d="m 322.2003,328.1839 c 0,-24.4581 8.9422,-47.3527 24.4508,-65.0437 l -9.347,-8.3787 c -17.5008,19.9159 -27.6522,45.7824 -27.6522,73.4224 0,31.144 12.801,59.3037 33.4258,79.5062 l 0.47,-0.4215 27.6474,-24.7845 C 345.2111,358.664 339.8298,319.926 357.9086,290.084 l 9.5443,8.5556 c -13.7812,24.8958 -8.5306,56.3422 13.1394,75.42 l 9.4666,-8.4844 8.4197,-7.5492 8.7333,-7.8288 c -3.2664,-2.048 -6.0429,-4.8044 -8.1148,-8.0538 -2.5602,-4.0158 -4.0439,-8.7843 -4.0439,-13.8982 0,-11.4001 7.3721,-21.0816 17.6077,-24.5373 l 0.8807,-12.0308 c -17.0538,3.435 -29.9009,18.5037 -29.9009,36.5681 0,8.0438 2.5472,15.4941 6.8791,21.5875 l -8.356,7.4922 -0.0315,0.0284 c -13.6984,-18.1953 -12.852,-43.4563 1.899,-60.7045 L 355.9969,271.518 c -27.6004,31.6071 -28.3884,78.5191 -1.9533,111.0143 l -9.3515,8.3835 c -12.907,-15.6702 -21.0804,-35.3849 -22.3254,-56.9549 l -0.057,-0.0637 0.0507,-0.0454 c -0.1063,-1.876 -0.1601,-3.7655 -0.1601,-5.6679 z m 107.0286,-24.476 c 10.2356,3.4557 17.6076,13.1375 17.6076,24.5373 0,5.1139 -1.4836,9.8824 -4.0436,13.8979 -2.0718,3.2494 -4.8484,6.0061 -8.1144,8.0538 l 8.7329,7.8288 8.4206,7.5486 -8e-4,9e-4 9.4666,8.4844 c 21.67,-19.0778 26.9206,-50.5242 13.1394,-75.42 l 9.5442,-8.5556 c 18.0786,29.842 12.6976,68.58 -13.2865,92.4001 l 27.6486,24.7856 0.4688,0.4204 c 20.6249,-20.2025 33.4259,-48.3622 33.4259,-79.5062 0,-27.64 -10.1515,-53.5065 -27.6523,-73.4224 l -9.3469,8.3787 c 15.5083,17.691 24.4505,40.5856 24.4505,65.0437 0,1.9024 -0.0536,3.7919 -0.1599,5.6679 l 0.0507,0.0454 -0.0569,0.0637 c -1.245,21.57 -9.4184,41.2847 -22.3257,56.9549 l -9.3512,-8.3835 c 26.435,-32.4952 25.6467,-79.4072 -1.9534,-111.0143 l -28.0346,25.1308 c 14.7512,17.2482 15.5976,42.5092 1.8992,60.7045 l -0.0317,-0.0284 -8.356,-7.4922 c 4.3319,-6.0936 6.8791,-13.5439 6.8791,-21.5875 0,-18.0644 -12.8472,-33.1328 -29.9007,-36.5681 l 0.8805,12.0308 z" /></g></g></svg>
|
||||
|
After Width: | Height: | Size: 3.9 KiB |
BIN
public/svgs/portainer.png
Normal file
|
After Width: | Height: | Size: 6.8 KiB |
13
public/svgs/postiz.svg
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
<?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 width="100%" height="100%" viewBox="0 0 370 410" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
|
||||
<g transform="matrix(1,0,0,1,-11583.9,-1689)">
|
||||
<g transform="matrix(1,0,0,1,-0.097081,-0.236295)">
|
||||
<g transform="matrix(12.8208,0,0,12.8208,11584,1689.24)">
|
||||
<path d="M4.902,4.617C4.924,4.976 4.955,5.38 4.991,5.842L6.282,22.516C6.426,24.379 6.498,25.311 6.916,25.995C7.283,26.596 7.832,27.066 8.482,27.337C9.222,27.644 10.154,27.572 12.018,27.428L24.788,26.44C25.997,26.346 26.813,26.283 27.424,26.136C27.219,26.617 26.903,27.046 26.498,27.385C25.885,27.9 24.974,28.11 23.153,28.531L10.672,31.41C8.85,31.83 7.939,32.04 7.162,31.846C6.478,31.675 5.866,31.292 5.413,30.752C4.898,30.138 4.688,29.228 4.268,27.406L0.509,11.111C0.089,9.289 -0.121,8.379 0.073,7.601C0.243,6.917 0.626,6.305 1.166,5.852C1.78,5.337 2.691,5.127 4.512,4.707L4.902,4.617Z" style="fill:rgb(97,43,211);fill-rule:nonzero;"/>
|
||||
<path d="M18.098,14.088C17.864,14.346 17.565,14.489 17.199,14.517C16.947,14.537 16.739,14.504 16.577,14.417C16.414,14.317 16.293,14.213 16.214,14.106L15.76,8.23C15.845,7.87 16,7.597 16.226,7.41C16.451,7.209 16.689,7.098 16.942,7.079C17.04,7.071 17.176,7.089 17.349,7.132C17.536,7.174 17.729,7.3 17.929,7.511C18.128,7.708 18.308,8.026 18.469,8.465C18.644,8.904 18.762,9.509 18.821,10.281C18.858,10.759 18.86,11.246 18.828,11.743C18.809,12.225 18.737,12.668 18.613,13.073C18.503,13.477 18.332,13.815 18.098,14.088Z" style="fill:white;fill-rule:nonzero;"/>
|
||||
<path d="M5.956,5.092C5.857,3.82 5.808,3.184 6.018,2.679C6.203,2.235 6.523,1.861 6.934,1.61C7.4,1.325 8.036,1.275 9.308,1.177L23.423,0.085C24.695,-0.014 25.331,-0.063 25.836,0.147C26.281,0.332 26.655,0.652 26.906,1.063C27.191,1.529 27.24,2.165 27.339,3.437L28.733,21.453C28.831,22.725 28.88,23.361 28.671,23.866C28.486,24.311 28.165,24.685 27.755,24.936C27.288,25.221 26.652,25.27 25.38,25.369L11.265,26.461C9.993,26.559 9.357,26.609 8.852,26.399C8.408,26.214 8.034,25.893 7.783,25.483C7.498,25.016 7.448,24.38 7.35,23.108L5.956,5.092ZM15.631,6.566L15.509,4.986L12.476,5.22L13.758,21.797L16.732,20.804L16.336,15.686C16.506,15.871 16.751,16.028 17.072,16.159C17.392,16.275 17.819,16.313 18.352,16.272C19.096,16.214 19.702,16.005 20.168,15.644C20.648,15.268 21.014,14.802 21.268,14.245C21.521,13.689 21.678,13.069 21.738,12.387C21.813,11.703 21.824,11.024 21.772,10.35C21.699,9.409 21.539,8.616 21.291,7.972C21.044,7.327 20.736,6.821 20.369,6.454C20.014,6.071 19.612,5.806 19.163,5.657C18.728,5.507 18.271,5.45 17.794,5.487C17.274,5.528 16.839,5.653 16.488,5.864C16.136,6.061 15.85,6.294 15.631,6.566Z" style="fill:white;"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3 KiB |
9
public/svgs/readeck.svg
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="240" height="240" viewBox="0 0 240 240">
|
||||
<path fill-rule="nonzero" fill="rgb(98.431373%, 80.784314%, 33.333333%)" fill-opacity="1" d="M 191.011719 69.769531 L 91.191406 116.308594 L 91.191406 187.800781 L 218.394531 128.492188 Z M 191.011719 69.769531 "/>
|
||||
<path fill-rule="nonzero" fill="rgb(27.45098%, 73.333333%, 83.921569%)" fill-opacity="1" d="M 91.191406 117.808594 L 91.191406 189.304688 L 197.078125 238.671875 L 190.730469 199.960938 L 224.460938 179.949219 Z M 91.191406 117.808594 "/>
|
||||
<path fill-rule="nonzero" fill="rgb(3.529412%, 43.529412%, 52.54902%)" fill-opacity="1" d="M 26.386719 38.96875 L 91.191406 38.96875 L 91.191406 230.949219 L 26.386719 230.949219 Z M 26.386719 38.96875 "/>
|
||||
<path fill-rule="nonzero" fill="rgb(0%, 0%, 0%)" fill-opacity="0.313726" d="M 26.382812 38.96875 L 26.382812 43.105469 L 213.953125 130.5625 L 218.398438 128.488281 Z M 26.382812 38.96875 "/>
|
||||
<path fill-rule="nonzero" fill="rgb(27.45098%, 73.333333%, 83.921569%)" fill-opacity="1" d="M 91.191406 3.222656 L 26.386719 38.96875 L 218.394531 128.492188 L 218.394531 57 Z M 91.191406 3.222656 "/>
|
||||
<path fill-rule="nonzero" fill="rgb(100%, 100%, 100%)" fill-opacity="1" d="M 91.191406 69.1875 L 91.191406 116.308594 L 141.726562 92.75 Z M 91.191406 69.1875 "/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.4 KiB |
BIN
public/svgs/web-check.png
Normal file
|
After Width: | Height: | Size: 22 KiB |
119
public/svgs/wikijs.svg
Normal file
|
|
@ -0,0 +1,119 @@
|
|||
<?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 width="100%" height="100%" viewBox="0 0 128 128" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
|
||||
<path d="M63.692,64.781c0,0 20.812,0.75 30.375,9c9.562,8.25 16.125,24 13.312,37.688c-5.625,-1.313 -29.625,-5.438 -39.375,-17.438c-9.75,-12 -9.375,-20.437 -8.25,-25.5c1.125,-5.062 3.938,-3.75 3.938,-3.75" style="fill:#1c9cf3;fill-rule:nonzero;"/>
|
||||
<path d="M60.044,68.582c-0.475,2.139 -0.988,5.498 0.046,9.953c1.125,4.848 3.801,10.068 8.198,15.31c10.06,11.993 38.391,16.857 38.734,16.932c1.078,-6.234 0.351,-12.729 -2.174,-19.516c-2.494,-6.705 -6.5,-12.669 -11.279,-16.793c-9.415,-8.122 -30.26,-8.963 -30.469,-8.971l-0.215,-0.007l-0.155,-0.081c-0.002,0 -0.177,-0.068 -0.418,-0.068c-0.998,0 -1.803,1.151 -2.268,3.241Z" style="fill:url(#_Radial1);fill-rule:nonzero;"/>
|
||||
<path d="M58.254,64.781c0,0 2.625,5.438 -3.562,13.688c-6.188,8.25 -19.125,21.562 -51.375,18.75c1.125,-7.688 6.75,-15.563 12.937,-21.188c6.188,-5.625 20.063,-11.437 29.25,-11.625c9.188,-0.187 12.75,0.375 12.75,0.375" style="fill:#04bbf3;fill-rule:nonzero;"/>
|
||||
<path d="M45.667,65.135c-4.286,0.086 -10.037,1.469 -15.783,3.791c-5.597,2.263 -10.53,5.128 -13.534,7.859c-6.762,6.148 -11.116,13.417 -12.413,19.94c2.596,0.201 7.447,0.302 7.447,0.302c11.549,0 21.195,-2.117 29.11,-6.626c7.017,-3.996 11.231,-8.995 13.79,-12.407c4.909,-6.545 4.149,-11.122 3.717,-12.555c-1.08,-0.116 -3.81,-0.344 -8.669,-0.344c-1.165,0 -2.398,0.013 -3.665,0.04Z" style="fill:url(#_Linear2);fill-rule:nonzero;"/>
|
||||
<path d="M123.879,45.656c0,0 -3.75,10.875 -22.125,16.125c-18.375,5.25 -38.062,1.875 -38.062,1.875c0,0 4.687,-12.375 18.187,-18.187c13.5,-5.813 37.313,-0.563 42,0.187" style="fill:#02bef3;fill-rule:nonzero;"/>
|
||||
<path d="M81.544,46.68c-10.988,4.731 -16.174,13.887 -17.695,17.055c2.266,0.309 7.463,0.901 13.983,0.901c8.656,0 16.566,-1.005 23.51,-2.989c14.825,-4.235 20.235,-12.672 21.72,-15.505c-0.243,-0.043 -17.126,-3.378 -26.758,-3.378c-6.904,0 -10.593,2.121 -14.76,3.916Z" style="fill:url(#_Radial3);fill-rule:nonzero;"/>
|
||||
<path d="M57.921,65.406c0,0 -26.74,-1.259 -42.436,-12.71c-15.695,-11.451 -15.333,-15.226 -15.333,-15.226c0,0 17.598,-0.054 26.286,3.078c8.688,3.133 22.335,11.948 31.483,24.858" style="fill:#02bef3;fill-rule:nonzero;"/>
|
||||
<path d="M16.409,52.486c6.069,4.428 13.396,7.559 22.006,9.665c0.002,0.001 0.002,0.001 0.004,0.001c9.149,1.098 16.735,2.791 18.559,2.946c-4.016,-5.462 -9.015,-10.404 -14.381,-14.517c-5.193,-3.99 -10.674,-7.143 -15.228,-8.943c-0.845,-0.336 -1.74,-0.638 -2.662,-0.915c-8.018,-2.397 -21.465,-2.553 -23.533,-2.583c0.509,0.942 2.299,4.909 15.235,14.346Z" style="fill:url(#_Radial4);fill-rule:nonzero;"/>
|
||||
<path d="M58.113,67.998c2.377,0.304 3.66,5.62 2.862,11.865c-0.798,6.244 -3.376,11.067 -5.754,10.763c-2.377,-0.303 -3.66,-5.62 -2.862,-11.864c0.798,-6.245 3.376,-11.068 5.754,-10.764Z" style="fill:url(#_Radial5);"/>
|
||||
<g>
|
||||
<path d="M61.629,64.651c-7.957,1.497 3.291,37.119 15.337,42.529c23.156,10.401 35.993,-9.611 35.993,-16.859c0,-7.249 -31.885,-29.326 -51.33,-25.67Z" style="fill:url(#_Radial6);fill-rule:nonzero;"/>
|
||||
<path d="M50.386,74.833c-2.895,5.261 20.365,23.165 30.768,21.166c10.402,-2 24.271,-12.529 23.192,-18.252c-1.079,-5.724 -19.995,-21.583 -35.132,-15.913c-9.928,3.719 -15.933,7.738 -18.828,12.999Z" style="fill:url(#_Radial7);fill-rule:nonzero;"/>
|
||||
<path d="M60.31,77.16c-2.178,5.597 13.079,21.534 23.128,18.182c10.048,-3.352 22.409,-15.617 20.586,-21.148c-1.824,-5.532 -22.664,-18.761 -36.922,-11.146c-9.351,4.994 -4.615,8.515 -6.792,14.112Z" style="fill:url(#_Radial8);fill-rule:nonzero;"/>
|
||||
<path d="M58.727,74.603c-1.855,4.721 11.081,18.141 19.616,15.304c8.535,-2.837 19.043,-13.192 17.501,-17.853c-1.542,-4.662 -19.221,-15.793 -31.334,-9.357c-7.946,4.221 -3.928,7.185 -5.783,11.906Z" style="fill:url(#_Radial9);fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g>
|
||||
<path d="M61.553,74.101c-1.577,4.793 -19.173,24.596 -31.313,27.374c-12.14,2.779 -24.092,-9.922 -25.211,-15.785c-1.119,-5.862 17.202,-22.572 35.975,-24.02c12.313,-0.95 23.195,4.394 20.549,12.431" style="fill:url(#_Radial10);fill-rule:nonzero;"/>
|
||||
<path d="M61.211,71.442c-1.214,5.581 -17.369,27.784 -29.357,30.15c-11.989,2.368 -24.988,-13.673 -26.567,-20.736c-1.579,-7.063 15.545,-25.529 34.304,-25.799c12.305,-0.176 23.657,7.026 21.62,16.385" style="fill:url(#_Radial11);fill-rule:nonzero;"/>
|
||||
<path d="M52.51,74.882c-1.717,3.102 -15.803,13.833 -23.882,13.516c-8.079,-0.316 -13.708,-11.577 -13.531,-15.946c0.177,-4.369 14.254,-12.769 26.319,-10.259c7.913,1.647 13.974,7.488 11.094,12.689" style="fill:url(#_Radial12);fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<path d="M34.746,69.666c-3.518,0.435 -20.481,-4.645 -24.977,-11.365c-4.497,-6.719 1.299,-17.895 4.937,-20.322c3.637,-2.426 18.71,4.018 23.777,15.251c3.322,7.368 2.164,15.705 -3.737,16.436" style="fill:url(#_Radial13);fill-rule:nonzero;"/>
|
||||
<g>
|
||||
<path d="M96.436,40.499c15.231,-2.015 28.385,2.308 29.356,9.649c0.971,7.34 -10.605,14.936 -25.836,16.951c-15.231,2.015 -28.385,-2.308 -29.356,-9.648c-0.971,-7.341 10.606,-14.937 25.836,-16.952Z" style="fill:url(#_Radial14);"/>
|
||||
<path d="M99.526,41.492c13.736,1.417 24.292,8.341 23.559,15.452c-0.734,7.111 -12.482,11.734 -26.218,10.316c-13.737,-1.417 -24.293,-8.341 -23.559,-15.452c0.733,-7.111 12.481,-11.734 26.218,-10.316Z" style="fill:url(#_Radial15);"/>
|
||||
<path d="M89.733,43.795c11.582,-1.429 21.602,2.408 22.361,8.563c0.76,6.154 -8.027,12.311 -19.609,13.74c-11.581,1.429 -21.601,-2.407 -22.36,-8.562c-0.76,-6.154 8.027,-12.311 19.608,-13.741Z" style="fill:url(#_Radial16);"/>
|
||||
</g>
|
||||
<path d="M59.353,65.162c0.022,0.369 0.978,7.846 -5.49,10.654c-5.003,2.171 -11.154,3.242 -24.792,-2.947c-13.638,-6.189 -18.377,-15.18 -18.377,-15.18c0,0 7.628,2.802 12.367,3.153c4.739,0.351 16.99,2.102 20.11,2.685c3.121,0.585 8.669,0.117 10.749,-0.349c2.081,-0.468 5.202,-1.752 5.433,1.984" style="fill:#b3c3ce;fill-rule:nonzero;"/>
|
||||
<path d="M29.071,72.494c13.639,6.188 19.79,5.117 24.792,2.948c6.468,-2.809 5.512,-10.287 5.49,-10.655c-0.232,-3.736 -3.352,-2.452 -5.432,-1.984c-2.081,0.467 -7.49,0.137 -11.979,-0.178c-5.344,-0.375 -13.969,-1.5 -18.88,-2.158c-4.71,-0.631 -12.368,-3.153 -12.368,-3.153c0,0 4.74,8.991 18.377,15.18Z" style="fill:url(#_Linear17);fill-rule:nonzero;"/>
|
||||
<path d="M55.262,58.355c0,0 -4.342,-3.433 -7.875,-7.169c-3.534,-3.735 -14.943,-14.538 -17.77,-17.466c-2.826,-2.928 -10.5,-12.924 -11.51,-17.164c-2.322,5.149 -3.836,14.539 -1.009,23.626c2.826,9.087 9.39,15.648 18.072,19.284c8.683,3.634 16.255,3.432 18.375,3.432c2.121,0 5.049,-1.413 1.717,-4.543" style="fill:#f5f6f2;fill-rule:nonzero;"/>
|
||||
<path d="M17.473,40.182c2.827,9.086 9.39,15.649 18.073,19.283c8.682,3.635 16.254,3.687 18.375,3.687c1.197,0 4.989,-0.152 5.177,-0.715c0.403,-1.21 -1.926,-2.107 -3.375,-3.468c-3.848,-3.042 -3.776,-3.358 -7.961,-7.782c-3.534,-3.736 -14.943,-14.539 -17.769,-17.467c-2.827,-2.928 -10.502,-12.923 -11.511,-17.165c-2.322,5.15 -3.837,14.54 -1.009,23.627Z" style="fill:url(#_Linear18);fill-rule:nonzero;"/>
|
||||
<path d="M103.337,21.668c-3.75,3.375 -10.395,7.863 -16.77,11.988c-6.375,4.125 -10.5,11.063 -15.375,18.375c-4.875,7.313 -9.75,10.875 -9.75,10.875c0,0 7.687,1.125 15,1.125c11.256,0 24,-9.375 28.687,-14.437c4.688,-5.063 7.838,-13.311 7.875,-21.75c0.043,-9.861 -4.519,-11.792 -4.519,-11.792c0,0 -1.398,2.24 -5.148,5.615Z" style="fill:url(#_Linear19);fill-rule:nonzero;"/>
|
||||
<path d="M103.865,20.907c-3.751,3.375 -11.298,8.624 -17.673,12.749c-6.375,4.125 -10.5,11.063 -15.375,18.375c-3.751,5.625 -8.444,8.724 -10.41,10.329c-0.59,0.482 -0.934,1.765 -0.934,1.765c6.769,0.99 8.351,-0.094 16.594,-0.094c11.255,0 24,-9.375 28.687,-14.437c4.688,-5.063 7.688,-13.313 7.875,-21.75c0.188,-8.438 -4.125,-11.813 -4.125,-11.813c0,0 -0.89,1.501 -4.639,4.876Z" style="fill:url(#_Linear20);fill-rule:nonzero;"/>
|
||||
<g>
|
||||
<path d="M42.638,45.578c8.133,5.258 12.662,12.735 10.107,16.686c-2.555,3.952 -11.232,2.89 -19.365,-2.368c-8.132,-5.259 -12.661,-12.736 -10.106,-16.687c2.555,-3.951 11.232,-2.89 19.364,2.369Z" style="fill:url(#_Radial21);"/>
|
||||
<path d="M41.855,45.022c7.726,5.84 12.065,13.139 9.684,16.29c-2.382,3.151 -10.588,0.968 -18.314,-4.871c-7.726,-5.839 -12.065,-13.139 -9.684,-16.29c2.382,-3.151 10.588,-0.968 18.314,4.871Z" style="fill:url(#_Radial22);"/>
|
||||
</g>
|
||||
<g>
|
||||
<path d="M76.747,50.134c8.038,-4.494 15.957,-5.649 17.674,-2.578c1.717,3.071 -3.415,9.213 -11.452,13.706c-8.038,4.494 -15.958,5.649 -17.674,2.578c-1.717,-3.071 3.414,-9.213 11.452,-13.706Z" style="fill:url(#_Radial23);"/>
|
||||
<path d="M79.138,46.315c7.951,-4.445 15.94,-5.31 17.83,-1.93c1.889,3.38 -3.032,9.733 -10.983,14.178c-7.951,4.445 -15.94,5.31 -17.83,1.93c-1.889,-3.38 3.032,-9.733 10.983,-14.178Z" style="fill:url(#_Radial24);"/>
|
||||
<path d="M78.132,49.395c7.5,-5.169 15.482,-6.621 17.812,-3.24c2.33,3.381 -1.867,10.323 -9.367,15.492c-7.5,5.17 -15.481,6.622 -17.812,3.241c-2.33,-3.381 1.867,-10.323 9.367,-15.493Z" style="fill:url(#_Radial25);"/>
|
||||
<path d="M87.314,42.046c2.878,-6.448 7.508,-10.659 10.332,-9.399c2.825,1.261 2.781,7.519 -0.098,13.967c-2.878,6.448 -7.508,10.659 -10.332,9.399c-2.824,-1.261 -2.78,-7.52 0.098,-13.967Z" style="fill:url(#_Radial26);"/>
|
||||
</g>
|
||||
<path d="M24.702,32.262c-0.805,5.902 0.586,11.977 3.363,15.977c2.778,4.001 10.763,11.808 18.631,12.917c5.111,0.72 10.596,0.69 10.596,0.69c0,0 -3.058,-2.97 -5.745,-8.561c-2.687,-5.591 -4.888,-10.846 -8.937,-14.358c-4.05,-3.511 -8.254,-7.303 -10.543,-10.031c-2.288,-2.729 -3.044,-4.431 -3.044,-4.431c0,0 -3.38,0.899 -4.321,7.797Z" style="fill:url(#_Linear27);fill-rule:nonzero;"/>
|
||||
<path d="M24.965,32.299c-0.7,5.916 0.585,11.978 3.363,15.978c2.778,3.999 10.762,11.808 18.63,12.915c5.762,0.813 6.31,1.128 11.139,1.102c0,0 -3.6,-3.381 -6.288,-8.972c-2.688,-5.591 -4.887,-10.847 -8.937,-14.358c-4.05,-3.51 -8.808,-7.923 -11.097,-10.651c-2.289,-2.728 -2.764,-3.865 -2.764,-3.865c0,0 -3.347,1.934 -4.046,7.851Z" style="fill:url(#_Linear28);fill-rule:nonzero;"/>
|
||||
<g>
|
||||
<path d="M55.714,66.066c1.06,3.068 -2.837,7.203 -8.698,9.227c-5.86,2.024 -11.478,1.176 -12.538,-1.892c-1.059,-3.069 2.838,-7.203 8.698,-9.227c5.86,-2.024 11.478,-1.176 12.538,1.892Z" style="fill:url(#_Radial29);"/>
|
||||
<path d="M53.204,68.127c0.12,2.902 -4.178,5.44 -9.591,5.663c-5.413,0.223 -9.905,-1.952 -10.024,-4.854c-0.12,-2.903 4.178,-5.44 9.591,-5.664c5.413,-0.223 9.905,1.953 10.024,4.855Z" style="fill:url(#_Radial30);"/>
|
||||
<path d="M58.03,66.776c0.851,2.014 -2.078,5.179 -6.538,7.064c-4.459,1.885 -8.771,1.78 -9.622,-0.233c-0.851,-2.014 2.078,-5.179 6.538,-7.064c4.46,-1.885 8.771,-1.78 9.622,0.233Z" style="fill:url(#_Radial31);"/>
|
||||
</g>
|
||||
<path d="M31.673,65.694c2.166,3.131 5.442,5.398 8.477,6.086c3.035,0.689 10.168,0.927 14.358,-1.942c2.722,-1.865 5.295,-4.244 5.295,-4.244c0,0 -2.723,-0.082 -6.401,-1.561c-3.679,-1.478 -6.984,-3.008 -10.407,-2.918c-3.425,0.09 -7.043,0.115 -9.299,-0.185c-2.257,-0.299 -3.348,-0.777 -3.348,-0.777c0,0 -1.205,1.882 1.325,5.541Z" style="fill:url(#_Linear32);fill-rule:nonzero;"/>
|
||||
<path d="M31.813,65.599c2.221,3.091 5.441,5.396 8.476,6.086c3.036,0.688 10.17,0.928 14.358,-1.942c3.068,-2.103 3.462,-2.19 5.729,-4.285c0,0 -3.155,-0.042 -6.835,-1.52c-3.679,-1.478 -6.982,-3.009 -10.407,-2.918c-3.424,0.091 -7.572,0.061 -9.828,-0.239c-2.256,-0.3 -2.97,-0.631 -2.97,-0.631c0,0 -0.745,2.356 1.477,5.449Z" style="fill:url(#_Linear33);fill-rule:nonzero;"/>
|
||||
<path d="M98.926,64.619c-3.373,1.42 -18.374,0.622 -23.876,0c-5.503,-0.621 -11.189,-0.526 -12.25,-0.621c-3.796,-0.342 -3.106,0.887 -3.373,4.703c-0.621,10.563 3.373,12.694 6.302,13.138c2.93,0.443 5.593,-0.976 5.593,-0.976c0,0 29.024,-13.137 31.687,-14.558c0.496,-2.725 0.376,-3.586 -0.232,-3.586c-0.7,0 -2.047,1.14 -3.851,1.9Z" style="fill:url(#_Radial34);fill-rule:nonzero;"/>
|
||||
<g>
|
||||
<path d="M71.826,68.086c4.948,3.511 7.617,8.26 5.957,10.598c-1.659,2.338 -7.023,1.386 -11.971,-2.126c-4.947,-3.511 -7.616,-8.261 -5.957,-10.599c1.66,-2.338 7.024,-1.385 11.971,2.127Z" style="fill:url(#_Radial35);"/>
|
||||
<path d="M70.546,68.086c3.798,2.696 5.535,6.783 3.875,9.121c-1.659,2.338 -6.09,2.047 -9.889,-0.649c-3.798,-2.696 -5.534,-6.783 -3.875,-9.121c1.66,-2.338 6.091,-2.047 9.889,0.649Z" style="fill:url(#_Radial36);"/>
|
||||
<path d="M74.322,68.379c3.799,2.696 5.535,6.783 3.876,9.121c-1.66,2.338 -6.091,2.047 -9.889,-0.649c-3.799,-2.695 -5.535,-6.783 -3.875,-9.121c1.659,-2.338 6.09,-2.047 9.888,0.649Z" style="fill:url(#_Radial37);"/>
|
||||
</g>
|
||||
<path d="M61.502,69.307c2.637,4.341 9.236,7.059 12.286,7.682c3.05,0.622 6.968,-0.097 10.231,-2.06c3.811,-2.292 3.487,-4.503 3.487,-4.503c0,0 -1.191,-0.014 -3.37,-0.669c-2.18,-0.656 -5.468,-2.167 -8.551,-3.659c-3.083,-1.492 -6.724,-1.457 -10.686,-1.624c-3.961,-0.167 -6.476,-1.212 -6.476,-1.212c0,0 1.366,3.228 3.079,6.045Z" style="fill:url(#_Linear38);fill-rule:nonzero;"/>
|
||||
<path d="M61.415,69.164c2.635,4.34 9.235,7.059 12.285,7.68c3.05,0.622 6.933,-0.154 10.23,-2.058c3.298,-1.903 3.588,-4.357 3.588,-4.357c0,0 -0.786,0.008 -2.965,-0.647c-2.18,-0.656 -5.972,-2.337 -9.056,-3.829c-3.083,-1.491 -6.724,-1.457 -10.686,-1.623c-3.961,-0.168 -6.854,-1.429 -6.854,-1.429c1.203,2.843 1.527,3.085 3.458,6.263Z" style="fill:url(#_Linear39);fill-rule:nonzero;"/>
|
||||
<path d="M102.035,66.75c0,0 1.219,-0.938 1.125,-2.813c-0.093,-1.874 0.375,-4.687 -9.562,-10.781c-3.281,5.907 -14.625,21.657 -19.594,25.219c-4.969,3.563 -5.765,3.442 -5.765,3.442c0,0 2.871,-0.343 5.39,-2.223c2.722,-2.032 28.406,-12.844 28.406,-12.844" style="fill:#cbd3dd;fill-rule:nonzero;"/>
|
||||
<path d="M74.379,78.563c-3.085,2.212 -4.026,2.655 -4.716,2.945c0.257,-0.077 2.189,-0.583 4.341,-1.726c3,-1.594 28.406,-12.844 28.406,-12.844c0,-0.001 1.219,-0.938 1.125,-2.813c-0.093,-1.875 0.375,-4.687 -9.562,-10.781c-3.281,5.906 -14.625,21.657 -19.594,25.219Z" style="fill:url(#_Linear40);fill-rule:nonzero;"/>
|
||||
<path d="M58.915,67.448c-0.618,-0.001 -6.022,9.818 -3.491,21.069c0,-0.001 3.615,-4.339 4.058,-15.247c0.183,-4.5 -0.133,-5.823 -0.567,-5.823Z" style="fill:url(#_Linear41);fill-rule:nonzero;"/>
|
||||
<path d="M44.829,36.179c1.272,-1.24 5.597,-0.248 6.615,1.116c0.995,1.333 6.118,6.458 5.875,14.213c0.788,0.033 1.832,0.17 3.031,0.17c1.035,0 1.994,-0.102 2.781,-0.152c-0.252,-7.765 4.878,-12.897 5.873,-14.231c1.017,-1.364 5.343,-2.356 6.615,-1.116c1.273,1.24 -2.036,1.116 -3.562,0.744c-4.941,1.094 -8.097,12.039 -8.77,14.594c1.153,-0.063 1.897,0.018 1.897,0.781c0,1.156 -1.619,3.021 -3.872,3.221c0.092,0.464 0.627,3.053 0.024,5.777c-0.245,1.107 -2.519,2.36 -2.519,2.36c-2.415,-7.912 -0.023,-8.682 0.01,-8.748c-1.978,-0.296 -3.058,-1.549 -3.058,-2.61c0,-0.676 0.518,-0.817 1.388,-0.796c-0.681,-2.582 -3.835,-13.487 -8.765,-14.579c-1.527,0.372 -4.835,0.496 -3.563,-0.744" style="fill:#00c6f9;fill-rule:nonzero;"/>
|
||||
<path d="M69.004,37.669c-0.995,1.335 -6.125,6.466 -5.873,14.232c-0.787,0.05 -1.746,0.152 -2.781,0.152c-1.199,0 -2.243,-0.137 -3.031,-0.17c0.243,-7.755 -4.88,-12.88 -5.874,-14.214c-1.018,-1.364 -5.344,-2.355 -6.616,-1.115c-1.272,1.24 2.036,1.115 3.563,0.743c4.93,1.093 8.084,11.998 8.765,14.58c-0.87,-0.02 -1.387,0.12 -1.387,0.796c0,1.061 0.786,2.39 2.763,2.684c-0.033,0.066 -1.658,1.242 0.284,8.674c0,0 3.102,-0.292 2.628,-6.64c-0.054,-0.732 -0.13,-1.318 -0.223,-1.782c2.252,-0.201 3.962,-1.781 3.962,-2.936c0,-0.763 -0.744,-0.844 -1.897,-0.781c0.674,-2.555 3.829,-13.5 8.77,-14.595c1.527,0.372 4.835,0.497 3.562,-0.743c-0.408,-0.398 -1.13,-0.566 -1.956,-0.566c-1.75,0 -3.968,0.755 -4.659,1.681Z" style="fill:url(#_Radial42);fill-rule:nonzero;"/>
|
||||
<path d="M48.011,24.197c-0.937,1.89 2.368,2.171 3.493,1.605c3.635,1.665 5.958,18.288 6.46,22.223c-0.641,-0.031 -1.022,0.183 -1.022,1.213c0,1.617 0.873,3.929 2.329,4.38c-0.024,0.1 -0.037,0.16 -0.037,0.16c0,0 -2.48,4.628 -0.417,14.753c0,0 2.307,-5.062 2.307,-12.099c0,-1.119 -0.096,-2.01 -0.165,-2.719c1.66,-0.305 2.92,-2.713 2.92,-4.475c0,-1.161 -0.547,-1.285 -1.397,-1.189c0.387,-4.644 1.969,-20.385 6.463,-22.247c1.125,0.566 4.286,0.354 3.348,-1.536c-0.937,-1.89 -4.255,-0.383 -5.571,1.387c-1.445,1.942 -4.932,10.629 -4.747,22.466c-0.579,0.076 -0.896,0.174 -1.658,0.174c-0.883,0 -1.653,-0.208 -2.234,-0.259c0.179,-11.822 -3.677,-19.606 -4.329,-21.666c-0.616,-1.949 -2.533,-3.101 -4.027,-3.101c-0.755,0 -1.401,0.295 -1.716,0.93Z" style="fill:url(#_Linear43);fill-rule:nonzero;"/>
|
||||
<path d="M48.011,24.565c-0.937,1.874 2.368,2.154 3.493,1.591c3.635,1.652 5.958,18.142 6.46,22.047c-0.641,-0.031 -1.022,0.181 -1.022,1.203c0,1.604 0.873,3.897 2.329,4.343c-0.024,0.1 -0.037,0.159 -0.037,0.159c0,0 -4.295,14.835 -1.471,24.549c0,0 3.709,-12.317 3.361,-21.915c-0.04,-1.109 -0.096,-1.994 -0.165,-2.697c1.66,-0.303 2.92,-2.691 2.92,-4.439c0,-1.153 -0.547,-1.276 -1.397,-1.181c0.387,-4.607 1.969,-20.222 6.463,-22.069c1.125,0.563 4.286,0.352 3.348,-1.523c-0.937,-1.875 -4.255,-0.38 -5.571,1.375c-1.445,1.927 -4.932,10.545 -4.747,22.287c-0.579,0.075 -0.896,0.174 -1.658,0.174c-0.883,0 -1.653,-0.207 -2.234,-0.258c0.179,-11.728 -3.677,-19.448 -4.329,-21.492c-0.616,-1.934 -2.533,-3.077 -4.027,-3.077c-0.754,0.001 -1.401,0.293 -1.716,0.923Z" style="fill:url(#_Linear44);fill-rule:nonzero;"/>
|
||||
<path d="M64.284,58.419c0,0 3.743,-2.96 6.791,-6.181c3.047,-3.222 12.885,-12.537 15.323,-15.063c2.438,-2.524 9.055,-11.144 9.926,-14.801c2.003,4.441 3.308,12.538 0.87,20.373c-2.437,7.836 -8.097,13.496 -15.584,16.63c-7.488,3.134 -14.018,2.96 -15.845,2.96c-1.829,0 -4.354,-1.219 -1.481,-3.918" style="fill:#f5f6f2;fill-rule:nonzero;"/>
|
||||
<path d="M86.075,37.175c-2.439,2.525 -12.276,11.84 -15.323,15.062c-3.609,3.816 -3.547,4.088 -6.865,6.711c-1.25,1.174 -3.205,2.508 -2.946,3.073c0.259,0.564 3.467,0.316 4.5,0.316c1.828,0 8.358,0.174 15.846,-2.96c7.487,-3.135 13.146,-8.794 15.584,-16.629c2.439,-7.836 1.132,-15.933 -0.871,-20.374c-0.87,3.658 -7.487,12.277 -9.925,14.801Z" style="fill:url(#_Linear45);fill-rule:nonzero;"/>
|
||||
<defs>
|
||||
<radialGradient id="_Radial1" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="matrix(-66.1387,0,-0,66.1387,60.5806,63.95)"><stop offset="0" style="stop-color:#3d4ead;stop-opacity:1"/><stop offset="1" style="stop-color:#00c0f3;stop-opacity:1"/></radialGradient>
|
||||
<linearGradient id="_Linear2" x1="0" y1="0" x2="1" y2="0" gradientUnits="userSpaceOnUse" gradientTransform="matrix(-54.7355,0,0,-32.1015,58.3206,81.1455)"><stop offset="0" style="stop-color:#3f51b4;stop-opacity:1"/><stop offset="1" style="stop-color:#00c0f3;stop-opacity:1"/></linearGradient>
|
||||
<radialGradient id="_Radial3" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="matrix(-66.1374,0,-0,66.1374,60.5808,63.95)"><stop offset="0" style="stop-color:#3d4ead;stop-opacity:1"/><stop offset="1" style="stop-color:#00c0f3;stop-opacity:1"/></radialGradient>
|
||||
<radialGradient id="_Radial4" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="matrix(-52.6361,-107.604,-12.8428,112.241,48.7863,138.585)"><stop offset="0" style="stop-color:#0072e9;stop-opacity:1"/><stop offset="1" style="stop-color:#00fdfe;stop-opacity:1"/></radialGradient>
|
||||
<radialGradient id="_Radial5" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="matrix(4.0052,0.526563,-1.46889,11.3112,56.6669,79.3122)"><stop offset="0" style="stop-color:#153e68;stop-opacity:0.34"/><stop offset="1" style="stop-color:#153e68;stop-opacity:0.01"/></radialGradient>
|
||||
<radialGradient id="_Radial6" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="matrix(-10.3568,10.999,26.0381,24.5177,74.5359,78.3911)"><stop offset="0" style="stop-color:#00336f;stop-opacity:1"/><stop offset="1" style="stop-color:#00336f;stop-opacity:0"/></radialGradient>
|
||||
<radialGradient id="_Radial7" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="matrix(-6.51962,11.4057,24.5674,14.4231,72.7521,72.772)"><stop offset="0" style="stop-color:#00336f;stop-opacity:0.5"/><stop offset="1" style="stop-color:#00336f;stop-opacity:0"/></radialGradient>
|
||||
<radialGradient id="_Radial8" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="matrix(-4.96046,12.1651,26.2531,11.0614,72.05,73.4244)"><stop offset="0" style="stop-color:#00336f;stop-opacity:0.5"/><stop offset="1" style="stop-color:#00336f;stop-opacity:0"/></radialGradient>
|
||||
<radialGradient id="_Radial9" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="matrix(-4.22491,10.2622,22.277,9.29717,68.699,71.4404)"><stop offset="0" style="stop-color:#00336f;stop-opacity:1"/><stop offset="1" style="stop-color:#00336f;stop-opacity:0"/></radialGradient>
|
||||
<radialGradient id="_Radial10" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="matrix(-9.78901,-10.0451,-28.1355,22.8978,42.6909,72.541)"><stop offset="0" style="stop-color:#002d68;stop-opacity:1"/><stop offset="1" style="stop-color:#002d68;stop-opacity:0"/></radialGradient>
|
||||
<radialGradient id="_Radial11" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="matrix(-10.6184,-12.7117,-26.5102,25.0697,42.1289,68.125)"><stop offset="0" style="stop-color:#002d68;stop-opacity:1"/><stop offset="1" style="stop-color:#002d68;stop-opacity:0"/></radialGradient>
|
||||
<radialGradient id="_Radial12" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="matrix(-4.66402,-8.96904,-21.2029,10.9396,40.8426,70.2218)"><stop offset="0" style="stop-color:#002d68;stop-opacity:1"/><stop offset="1" style="stop-color:#002d68;stop-opacity:0"/></radialGradient>
|
||||
<radialGradient id="_Radial13" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="matrix(4.51007,-9.04744,-21.3185,-10.7126,31.6527,57.4886)"><stop offset="0" style="stop-color:#002d68;stop-opacity:1"/><stop offset="1" style="stop-color:#002d68;stop-opacity:0"/></radialGradient>
|
||||
<radialGradient id="_Radial14" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="matrix(55.5618,-7.25333,2.08197,15.9483,70.5908,57.3802)"><stop offset="0" style="stop-color:#00326d;stop-opacity:1"/><stop offset="1" style="stop-color:#003b79;stop-opacity:0"/></radialGradient>
|
||||
<radialGradient id="_Radial15" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="matrix(50.0892,5.26339,-1.61895,15.4438,73.3147,51.7397)"><stop offset="0" style="stop-color:#00326d;stop-opacity:1"/><stop offset="1" style="stop-color:#003b79;stop-opacity:0"/></radialGradient>
|
||||
<radialGradient id="_Radial16" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="matrix(42.2509,-5.13094,1.62846,13.3715,70.1175,57.4772)"><stop offset="0" style="stop-color:#00326d;stop-opacity:1"/><stop offset="1" style="stop-color:#003b79;stop-opacity:0"/></radialGradient>
|
||||
<linearGradient id="_Linear17" x1="0" y1="0" x2="1" y2="0" gradientUnits="userSpaceOnUse" gradientTransform="matrix(-48.7206,0,-0,48.7206,59.4148,67.2287)"><stop offset="0" style="stop-color:#f5f7fa;stop-opacity:1"/><stop offset="0.53" style="stop-color:#f1f4f2;stop-opacity:1"/><stop offset="1" style="stop-color:#bad7e9;stop-opacity:1"/></linearGradient>
|
||||
<linearGradient id="_Linear18" x1="0" y1="0" x2="1" y2="0" gradientUnits="userSpaceOnUse" gradientTransform="matrix(-43.2077,0,-0,43.2077,59.144,39.7308)"><stop offset="0" style="stop-color:#fafafa;stop-opacity:1"/><stop offset="0.26" style="stop-color:#f1f6f8;stop-opacity:1"/><stop offset="0.73" style="stop-color:#dce5eb;stop-opacity:1"/><stop offset="1" style="stop-color:#bbcfda;stop-opacity:1"/></linearGradient>
|
||||
<linearGradient id="_Linear19" x1="0" y1="0" x2="1" y2="0" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0,-47.9791,-47.9791,-0,87.2229,64.0313)"><stop offset="0" style="stop-color:#fdfdff;stop-opacity:1"/><stop offset="0.26" style="stop-color:#f1f2f2;stop-opacity:1"/><stop offset="0.73" style="stop-color:#bfd2e0;stop-opacity:1"/><stop offset="1" style="stop-color:#afc0cc;stop-opacity:1"/></linearGradient>
|
||||
<linearGradient id="_Linear20" x1="0" y1="0" x2="1" y2="0" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0,-48.0543,-48.0543,-0,86.4289,64.0856)"><stop offset="0" style="stop-color:#f1f6f6;stop-opacity:1"/><stop offset="0.41" style="stop-color:#fdfdfd;stop-opacity:1"/><stop offset="0.55" style="stop-color:#f5f8fa;stop-opacity:1"/><stop offset="0.89" style="stop-color:#d6e1e7;stop-opacity:1"/><stop offset="0.98" style="stop-color:#c3d3dd;stop-opacity:1"/><stop offset="1" style="stop-color:#c3d3dd;stop-opacity:1"/></linearGradient>
|
||||
<radialGradient id="_Radial21" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="matrix(14.7354,9.52776,-4.62893,7.15901,38.0093,52.7366)"><stop offset="0" style="stop-color:#153e68;stop-opacity:1"/><stop offset="1" style="stop-color:#153e68;stop-opacity:0"/></radialGradient>
|
||||
<radialGradient id="_Radial22" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="matrix(13.9988,10.5803,-4.31511,5.70934,37.54,50.7316)"><stop offset="0" style="stop-color:#153e68;stop-opacity:1"/><stop offset="1" style="stop-color:#153e68;stop-opacity:0"/></radialGradient>
|
||||
<radialGradient id="_Radial23" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="matrix(14.5634,-8.14176,3.11074,5.56427,79.858,55.6982)"><stop offset="0" style="stop-color:#153e68;stop-opacity:1"/><stop offset="1" style="stop-color:#153e68;stop-opacity:0"/></radialGradient>
|
||||
<radialGradient id="_Radial24" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="matrix(14.4062,-8.05386,3.42371,6.12408,82.5616,52.4391)"><stop offset="0" style="stop-color:#153e68;stop-opacity:1"/><stop offset="1" style="stop-color:#153e68;stop-opacity:0"/></radialGradient>
|
||||
<radialGradient id="_Radial25" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="matrix(13.5894,-9.36638,4.22241,6.1262,82.3546,55.5213)"><stop offset="0" style="stop-color:#153e68;stop-opacity:1"/><stop offset="1" style="stop-color:#1a426b;stop-opacity:0"/></radialGradient>
|
||||
<radialGradient id="_Radial26" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="matrix(5.21516,-11.6826,5.1171,2.2843,92.4313,44.33)"><stop offset="0" style="stop-color:#153e68;stop-opacity:1"/><stop offset="1" style="stop-color:#1b436c;stop-opacity:0"/></radialGradient>
|
||||
<linearGradient id="_Linear27" x1="0" y1="0" x2="1" y2="0" gradientUnits="userSpaceOnUse" gradientTransform="matrix(4.72457,-33.536,33.536,4.72457,39.1596,60.0944)"><stop offset="0" style="stop-color:#fdfdff;stop-opacity:1"/><stop offset="0.26" style="stop-color:#f1f2f2;stop-opacity:1"/><stop offset="0.73" style="stop-color:#bfd2e0;stop-opacity:1"/><stop offset="1" style="stop-color:#afc0cc;stop-opacity:1"/></linearGradient>
|
||||
<linearGradient id="_Linear28" x1="0" y1="0" x2="1" y2="0" gradientUnits="userSpaceOnUse" gradientTransform="matrix(-33.3203,-0.000343575,0.000343575,-33.3203,58.0971,43.372)"><stop offset="0" style="stop-color:#fafafa;stop-opacity:1"/><stop offset="0.26" style="stop-color:#f1f6f8;stop-opacity:1"/><stop offset="0.73" style="stop-color:#dce5eb;stop-opacity:1"/><stop offset="1" style="stop-color:#bbcfda;stop-opacity:1"/></linearGradient>
|
||||
<radialGradient id="_Radial29" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="matrix(1.92018,5.55941,-10.6179,3.66735,45.0962,69.7332)"><stop offset="0" style="stop-color:#153e68;stop-opacity:1"/><stop offset="1" style="stop-color:#153e68;stop-opacity:0"/></radialGradient>
|
||||
<radialGradient id="_Radial30" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0.21678,5.25887,-9.80783,0.404296,43.3965,68.5313)"><stop offset="0" style="stop-color:#153e68;stop-opacity:1"/><stop offset="1" style="stop-color:#153e68;stop-opacity:0"/></radialGradient>
|
||||
<radialGradient id="_Radial31" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="matrix(1.54211,3.64848,-8.0801,3.41524,49.9501,70.1915)"><stop offset="0" style="stop-color:#153e68;stop-opacity:1"/><stop offset="1" style="stop-color:#153e68;stop-opacity:0"/></radialGradient>
|
||||
<linearGradient id="_Linear32" x1="0" y1="0" x2="1" y2="0" gradientUnits="userSpaceOnUse" gradientTransform="matrix(-12.2342,-17.8556,17.8556,-12.2342,50.4952,72.5871)"><stop offset="0" style="stop-color:#fdfdff;stop-opacity:1"/><stop offset="0.26" style="stop-color:#f1f2f2;stop-opacity:1"/><stop offset="0.73" style="stop-color:#bfd2e0;stop-opacity:1"/><stop offset="1" style="stop-color:#afc0cc;stop-opacity:1"/></linearGradient>
|
||||
<linearGradient id="_Linear33" x1="0" y1="0" x2="1" y2="0" gradientUnits="userSpaceOnUse" gradientTransform="matrix(-15.7162,14.3692,-14.3692,-15.7162,52.2159,56.533)"><stop offset="0" style="stop-color:#fafafa;stop-opacity:1"/><stop offset="0.26" style="stop-color:#f1f6f8;stop-opacity:1"/><stop offset="0.73" style="stop-color:#dce5eb;stop-opacity:1"/><stop offset="1" style="stop-color:#bbcfda;stop-opacity:1"/></linearGradient>
|
||||
<radialGradient id="_Radial34" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="matrix(-16.9591,0,-0,16.9591,81.3402,72.3216)"><stop offset="0" style="stop-color:#f9f9fa;stop-opacity:1"/><stop offset="1" style="stop-color:#f5f7f7;stop-opacity:1"/></radialGradient>
|
||||
<radialGradient id="_Radial35" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="matrix(8.96408,6.36252,-3.00685,4.23632,68.8193,72.3219)"><stop offset="0" style="stop-color:#153e68;stop-opacity:1"/><stop offset="1" style="stop-color:#153e68;stop-opacity:0"/></radialGradient>
|
||||
<radialGradient id="_Radial36" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="matrix(6.8821,4.88477,-3.00685,4.23632,67.5393,72.3219)"><stop offset="0" style="stop-color:#153e68;stop-opacity:1"/><stop offset="1" style="stop-color:#153e68;stop-opacity:0"/></radialGradient>
|
||||
<radialGradient id="_Radial37" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="matrix(6.8821,4.88477,-3.00685,4.23632,71.3156,72.6152)"><stop offset="0" style="stop-color:#153e68;stop-opacity:1"/><stop offset="1" style="stop-color:#153e68;stop-opacity:0"/></radialGradient>
|
||||
<linearGradient id="_Linear38" x1="0" y1="0" x2="1" y2="0" gradientUnits="userSpaceOnUse" gradientTransform="matrix(18.4986,-11.2373,-11.2373,-18.4986,64.0277,73.4655)"><stop offset="0" style="stop-color:#fdfdff;stop-opacity:1"/><stop offset="0.26" style="stop-color:#f1f2f2;stop-opacity:1"/><stop offset="0.73" style="stop-color:#bfd2e0;stop-opacity:1"/><stop offset="1" style="stop-color:#afc0cc;stop-opacity:1"/></linearGradient>
|
||||
<linearGradient id="_Linear39" x1="0" y1="0" x2="1" y2="0" gradientUnits="userSpaceOnUse" gradientTransform="matrix(8.40915,19.5646,19.5646,-8.40915,69.0669,58.1262)"><stop offset="0" style="stop-color:#fafafa;stop-opacity:1"/><stop offset="0.26" style="stop-color:#f1f6f8;stop-opacity:1"/><stop offset="0.73" style="stop-color:#dce5eb;stop-opacity:1"/><stop offset="1" style="stop-color:#bbcfda;stop-opacity:1"/></linearGradient>
|
||||
<linearGradient id="_Linear40" x1="0" y1="0" x2="1" y2="0" gradientUnits="userSpaceOnUse" gradientTransform="matrix(6.46873,14.3437,14.3437,-6.46873,80.3566,59.6296)"><stop offset="0" style="stop-color:#aebcd0;stop-opacity:1"/><stop offset="0.22" style="stop-color:#859bb9;stop-opacity:1"/><stop offset="0.53" style="stop-color:#a1b1c9;stop-opacity:1"/><stop offset="1" style="stop-color:#97a9c3;stop-opacity:1"/></linearGradient>
|
||||
<linearGradient id="_Linear41" x1="0" y1="0" x2="1" y2="0" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0,-21.0692,-21.0692,0,57.0961,88.5161)"><stop offset="0" style="stop-color:#c0cbda;stop-opacity:1"/><stop offset="0.02" style="stop-color:#c0cbda;stop-opacity:1"/><stop offset="0.11" style="stop-color:#d4dbe5;stop-opacity:1"/><stop offset="0.45" style="stop-color:#f5f6f9;stop-opacity:1"/><stop offset="0.59" style="stop-color:#fdfdfd;stop-opacity:1"/><stop offset="1" style="stop-color:#fcfdfd;stop-opacity:1"/></linearGradient>
|
||||
<radialGradient id="_Radial42" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="matrix(-18.2184,0,-0,12.4951,60.2241,50.0098)"><stop offset="0" style="stop-color:#3f51b5;stop-opacity:1"/><stop offset="1" style="stop-color:#04bbf3;stop-opacity:1"/></radialGradient>
|
||||
<linearGradient id="_Linear43" x1="0" y1="0" x2="1" y2="0" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0,-45.2637,-45.2637,-0,60.1552,68.5313)"><stop offset="0" style="stop-color:#afc0cc;stop-opacity:1"/><stop offset="0.24" style="stop-color:#afc0cc;stop-opacity:1"/><stop offset="0.74" style="stop-color:#f1f2f2;stop-opacity:1"/><stop offset="1" style="stop-color:#fdfdff;stop-opacity:1"/></linearGradient>
|
||||
<linearGradient id="_Linear44" x1="0" y1="0" x2="1" y2="0" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0,-46.5257,-46.5257,-0,60.1552,70.1682)"><stop offset="0" style="stop-color:#fafafa;stop-opacity:1"/><stop offset="0.26" style="stop-color:#f1f6f8;stop-opacity:1"/><stop offset="0.73" style="stop-color:#dce5eb;stop-opacity:1"/><stop offset="1" style="stop-color:#bbcfda;stop-opacity:1"/></linearGradient>
|
||||
<linearGradient id="_Linear45" x1="0" y1="0" x2="1" y2="0" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0,-39.9686,39.9686,-0,79.5662,62.3429)"><stop offset="0" style="stop-color:#f1f6f6;stop-opacity:1"/><stop offset="0.41" style="stop-color:#fdfdfd;stop-opacity:1"/><stop offset="0.55" style="stop-color:#f5f8fa;stop-opacity:1"/><stop offset="0.89" style="stop-color:#d6e1e7;stop-opacity:1"/><stop offset="0.98" style="stop-color:#c3d3dd;stop-opacity:1"/><stop offset="1" style="stop-color:#c3d3dd;stop-opacity:1"/></linearGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 33 KiB |
|
|
@ -4,8 +4,6 @@
|
|||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
|
||||
|
||||
html,
|
||||
body {
|
||||
@apply h-full bg-neutral-50 text-neutral-800 dark:bg-base dark:text-neutral-400;
|
||||
|
|
@ -172,10 +170,6 @@ section {
|
|||
@apply bg-error;
|
||||
}
|
||||
|
||||
/* [type='checkbox']:checked {
|
||||
background-image: url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='black' xmlns='http://www.w3.org/2000/svg'%3e%3cpath d='M12.207 4.793a1 1 0 010 1.414l-5 5a1 1 0 01-1.414 0l-2-2a1 1 0 011.414-1.414L6.5 9.086l4.293-4.293a1 1 0 011.414 0z'/%3e%3c/svg%3e");
|
||||
} */
|
||||
|
||||
.menu {
|
||||
@apply flex items-center gap-1;
|
||||
}
|
||||
|
|
@ -197,7 +191,7 @@ section {
|
|||
}
|
||||
|
||||
.scrollbar {
|
||||
@apply scrollbar-thumb-coollabs-100 dark:scrollbar-track-coolgray-200 scrollbar-track-neutral-200 scrollbar-w-2;
|
||||
@apply scrollbar-thumb-coollabs-100 dark:scrollbar-track-coolgray-200 scrollbar-track-neutral-200 scrollbar-thin;
|
||||
}
|
||||
|
||||
.main {
|
||||
|
|
|
|||
32
resources/js/bootstrap.js
vendored
|
|
@ -1,32 +0,0 @@
|
|||
/**
|
||||
* We'll load the axios HTTP library which allows us to easily issue requests
|
||||
* to our Laravel back-end. This library automatically handles sending the
|
||||
* CSRF token as a header based on the value of the "XSRF" token cookie.
|
||||
*/
|
||||
|
||||
// import axios from 'axios';
|
||||
// window.axios = axios;
|
||||
|
||||
// window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
|
||||
|
||||
/**
|
||||
* Echo exposes an expressive API for subscribing to channels and listening
|
||||
* for events that are broadcast by Laravel. Echo and event broadcasting
|
||||
* allows your team to easily build robust real-time web applications.
|
||||
*/
|
||||
|
||||
// import Echo from 'laravel-echo';
|
||||
|
||||
// import Pusher from 'pusher-js';
|
||||
// window.Pusher = Pusher;
|
||||
|
||||
// window.Echo = new Echo({
|
||||
// broadcaster: 'pusher',
|
||||
// key: import.meta.env.VITE_PUSHER_APP_KEY,
|
||||
// cluster: import.meta.env.VITE_PUSHER_APP_CLUSTER ?? 'mt1',
|
||||
// wsHost: import.meta.env.VITE_PUSHER_HOST ? import.meta.env.VITE_PUSHER_HOST : `ws-${import.meta.env.VITE_PUSHER_APP_CLUSTER}.pusher.com`,
|
||||
// wsPort: import.meta.env.VITE_PUSHER_PORT ?? 80,
|
||||
// wssPort: import.meta.env.VITE_PUSHER_PORT ?? 443,
|
||||
// forceTLS: (import.meta.env.VITE_PUSHER_SCHEME ?? 'https') === 'https',
|
||||
// enabledTransports: ['ws', 'wss'],
|
||||
// });
|
||||
|
|
@ -18,7 +18,7 @@
|
|||
@else
|
||||
<div>Transactional emails are not active on this instance.</div>
|
||||
<div>See how to set it in our <a class="dark:text-white" target="_blank"
|
||||
href="{{ config('constants.docs.base_url') }}">docs</a>, or how to
|
||||
href="{{ config('constants.urls.docs') }}">docs</a>, or how to
|
||||
manually reset password.
|
||||
</div>
|
||||
@endif
|
||||
|
|
|
|||
|
|
@ -14,8 +14,8 @@
|
|||
'w-full' => $fullWidth,
|
||||
])>
|
||||
@if (!$hideLabel)
|
||||
<label @class(['flex gap-4 px-0 min-w-fit label', 'opacity-40' => $disabled])>
|
||||
<span class="flex gap-2">
|
||||
<label @class(['flex gap-4 items-center px-0 min-w-fit label w-full cursor-pointer', 'opacity-40' => $disabled])>
|
||||
<span class="flex flex-grow gap-2">
|
||||
@if ($label)
|
||||
{!! $label !!}
|
||||
@else
|
||||
|
|
@ -25,11 +25,11 @@
|
|||
<x-helper :helper="$helper" />
|
||||
@endif
|
||||
</span>
|
||||
@endif
|
||||
<input @disabled($disabled) type="checkbox" {{ $attributes->merge(['class' => $defaultClass]) }}
|
||||
@if ($instantSave) wire:loading.attr="disabled" wire:click='{{ $instantSave === 'instantSave' || $instantSave == '1' ? 'instantSave' : $instantSave }}'
|
||||
wire:model={{ $id }} @else wire:model={{ $value ?? $id }} @endif />
|
||||
@if (!$hideLabel)
|
||||
</label>
|
||||
@endif
|
||||
<span class="flex-grow"></span>
|
||||
<input @disabled($disabled) type="checkbox" {{ $attributes->merge(['class' => $defaultClass]) }}
|
||||
@if ($instantSave) wire:loading.attr="disabled" wire:click='{{ $instantSave === 'instantSave' || $instantSave == '1' ? 'instantSave' : $instantSave }}'
|
||||
wire:model={{ $id }} @else wire:model={{ $value ?? $id }} @endif />
|
||||
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@
|
|||
$disableTwoStepConfirmation = data_get(InstanceSettings::get(), 'disable_two_step_confirmation');
|
||||
@endphp
|
||||
|
||||
<div x-data="{
|
||||
<div wire:ignore x-data="{
|
||||
modalOpen: false,
|
||||
step: {{ empty($checkboxes) ? 2 : 1 }},
|
||||
initialStep: {{ empty($checkboxes) ? 2 : 1 }},
|
||||
|
|
@ -106,8 +106,8 @@
|
|||
this.selectedActions.push(id);
|
||||
}
|
||||
}
|
||||
}" @keydown.escape.window="modalOpen = false; resetModal()" :class="{ 'z-40': modalOpen }"
|
||||
class="relative w-auto h-auto">
|
||||
}" @keydown.escape.window="modalOpen = false; resetModal()"
|
||||
:class="{ 'z-40': modalOpen }" class="relative w-auto h-auto">
|
||||
@if ($customButton)
|
||||
@if ($buttonFullWidth)
|
||||
<x-forms.button @click="modalOpen=true" class="w-full">
|
||||
|
|
@ -302,7 +302,8 @@
|
|||
</x-forms.button>
|
||||
@endif
|
||||
<x-forms.button
|
||||
x-bind:disabled="!disableTwoStepConfirmation && confirmWithText && userConfirmationText !== confirmationText"
|
||||
x-bind:disabled="!disableTwoStepConfirmation && confirmWithText && userConfirmationText !==
|
||||
confirmationText"
|
||||
class="w-auto" isError
|
||||
@click="
|
||||
if (dispatchEvent) {
|
||||
|
|
@ -337,11 +338,14 @@
|
|||
Your Password
|
||||
</label>
|
||||
<form @submit.prevent="false" @keydown.enter.prevent>
|
||||
<input type="text" name="username" autocomplete="username" value="{{ auth()->user()->email }}" style="display: none;">
|
||||
<input type="password" id="password-confirm-{{ $passwordConfirm }}" x-model="password"
|
||||
class="w-full input" placeholder="Enter your password" autocomplete="current-password">
|
||||
<input type="text" name="username" autocomplete="username"
|
||||
value="{{ auth()->user()->email }}" style="display: none;">
|
||||
<input type="password" id="password-confirm-{{ $passwordConfirm }}"
|
||||
x-model="password" class="w-full input" placeholder="Enter your password"
|
||||
autocomplete="current-password">
|
||||
</form>
|
||||
<p x-show="passwordError" x-text="passwordError" class="mt-1 text-sm text-red-500"></p>
|
||||
<p x-show="passwordError" x-text="passwordError" class="mt-1 text-sm text-red-500">
|
||||
</p>
|
||||
@error('password')
|
||||
<p class="mt-1 text-sm text-red-500">{{ $message }}</p>
|
||||
@enderror
|
||||
|
|
|
|||
|
|
@ -262,7 +262,7 @@
|
|||
your self-hosted instance?
|
||||
<x-forms.button>
|
||||
<a class="font-bold dark:text-white hover:no-underline"
|
||||
href="{{ config('coolify.contact') }}">Contact
|
||||
href="{{ config('constants.urls.contact') }}">Contact
|
||||
Us</a>
|
||||
</x-forms.button>
|
||||
</div>
|
||||
|
|
|
|||