diff --git a/.tinkerwell/snippets/DeleteUser.php b/.tinkerwell/snippets/DeleteUser.php new file mode 100644 index 000000000..bd562557b --- /dev/null +++ b/.tinkerwell/snippets/DeleteUser.php @@ -0,0 +1,22 @@ +first(); +$teams = $user->teams; +foreach ($teams as $team) { + $servers = $team->servers; + if ($servers->count() > 0) { + foreach ($servers as $server) { + dump($server); + $server->delete(); + } + } + dump($team); + $team->delete(); +} +if ($user) { + dump($user); + $user->delete(); +} diff --git a/app/Http/Livewire/Project/Service/StackForm.php b/app/Http/Livewire/Project/Service/StackForm.php index 30a3e7380..ebdb2d481 100644 --- a/app/Http/Livewire/Project/Service/StackForm.php +++ b/app/Http/Livewire/Project/Service/StackForm.php @@ -7,17 +7,34 @@ use Livewire\Component; class StackForm extends Component { public $service; - public $isConfigurationRequired = false; + public $fields = []; protected $listeners = ["saveCompose"]; - protected $rules = [ + public $rules = [ 'service.docker_compose_raw' => 'required', 'service.docker_compose' => 'required', 'service.name' => 'required', 'service.description' => 'nullable', ]; - public function mount () { - if ($this->service->applications->filter(fn($app) => str($app->image)->contains('minio/minio'))->count() > 0) { - $this->isConfigurationRequired = true; + public $validationAttributes = []; + public function mount() + { + $extraFields = $this->service->extraFields(); + foreach ($extraFields as $serviceName => $fields) { + foreach ($fields as $fieldKey => $field) { + $key = data_get($field, 'key'); + $value = data_get($field, 'value'); + $rules = data_get($field, 'rules'); + $isPassword = data_get($field, 'isPassword'); + $this->fields[$key] = [ + "serviceName" => $serviceName, + "key" => $key, + "name" => $fieldKey, + "value" => $value, + "isPassword" => $isPassword, + ]; + $this->rules["fields.$key.value"] = $rules; + $this->validationAttributes["fields.$key.value"] = $fieldKey; + } } } public function saveCompose($raw) @@ -32,6 +49,7 @@ class StackForm extends Component try { $this->validate(); $this->service->save(); + $this->service->saveExtraFields($this->fields); $this->service->parse(); $this->service->refresh(); $this->service->saveComposeConfigs(); diff --git a/app/Jobs/ApplicationDeploymentJob.php b/app/Jobs/ApplicationDeploymentJob.php index 71cf9026d..de32ad1fb 100644 --- a/app/Jobs/ApplicationDeploymentJob.php +++ b/app/Jobs/ApplicationDeploymentJob.php @@ -934,7 +934,16 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted } return implode(' ', $generated_healthchecks_commands); } + private function pull_latest_image($image) + { + $this->execute_remote_command( + ["echo -n 'Pulling latest image ($image) from the registry.'"], + [ + executeInDocker($this->deployment_uuid, "docker pull {$image}"), "hidden" => true + ] + ); + } private function build_image() { if ($this->application->build_pack === 'static') { @@ -948,6 +957,9 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted } if ($this->application->settings->is_static || $this->application->build_pack === 'static') { + if ($this->application->static_image) { + $this->pull_latest_image($this->application->static_image); + } if ($this->application->build_pack === 'static') { $dockerfile = base64_encode("FROM {$this->application->static_image} WORKDIR /usr/share/nginx/html/ @@ -1012,8 +1024,9 @@ COPY ./nginx.conf /etc/nginx/conf.d/default.conf"); ] ); } else { + // Pure Dockerfile based deployment $this->execute_remote_command([ - executeInDocker($this->deployment_uuid, "docker build $this->buildTarget $this->addHosts --network host -f {$this->workdir}{$this->dockerfile_location} {$this->build_args} --progress plain -t $this->production_image_name {$this->workdir}"), "hidden" => true + executeInDocker($this->deployment_uuid, "docker build --pull $this->buildTarget $this->addHosts --network host -f {$this->workdir}{$this->dockerfile_location} {$this->build_args} --progress plain -t $this->production_image_name {$this->workdir}"), "hidden" => true ]); } } @@ -1049,6 +1062,17 @@ COPY ./nginx.conf /etc/nginx/conf.d/default.conf"); private function start_by_compose_file() { + if ( + !$this->application->dockerfile && + ( + $this->application->build_pack === 'dockerimage' || + $this->application->build_pack === 'dockerfile') + ) { + $this->execute_remote_command( + ["echo -n 'Pulling latest images from the registry.'"], + [executeInDocker($this->deployment_uuid, "docker compose --project-directory {$this->workdir} pull"), "hidden" => true], + ); + } $this->execute_remote_command( ["echo -n 'Starting application (could take a while).'"], [executeInDocker($this->deployment_uuid, "docker compose --project-directory {$this->workdir} up --build -d"), "hidden" => true], diff --git a/app/Models/Service.php b/app/Models/Service.php index 14084f282..eabdc1d88 100644 --- a/app/Models/Service.php +++ b/app/Models/Service.php @@ -45,7 +45,168 @@ class Service extends BaseModel { return 'service'; } + public function extraFields() + { + $fields = collect([]); + $applications = $this->applications()->get(); + foreach ($applications as $application) { + $image = str($application->image)->before(':')->value(); + switch ($image) { + case str($image)->contains('minio'): + $console_url = $this->environment_variables()->where('key', 'MINIO_BROWSER_REDIRECT_URL')->first(); + $s3_api_url = $this->environment_variables()->where('key', 'MINIO_SERVER_URL')->first(); + $admin_user = $this->environment_variables()->where('key', 'SERVICE_USER_MINIO')->first(); + $admin_password = $this->environment_variables()->where('key', 'SERVICE_PASSWORD_MINIO')->first(); + $fields->put('MinIO', [ + 'Console URL' => [ + 'key' => data_get($console_url, 'key'), + 'value' => data_get($console_url, 'value'), + 'rules' => 'required|url', + ], + 'S3 API URL' => [ + 'key' => data_get($s3_api_url, 'key'), + 'value' => data_get($s3_api_url, 'value'), + 'rules' => 'required|url', + ], + 'Admin User' => [ + 'key' => data_get($admin_user, 'key'), + 'value' => data_get($admin_user, 'value'), + 'rules' => 'required', + ], + 'Admin Password' => [ + 'key' => data_get($admin_password, 'key'), + 'value' => data_get($admin_password, 'value'), + 'rules' => 'required', + 'isPassword' => true, + ], + ]); + break; + } + } + $databases = $this->databases()->get(); + foreach ($databases as $database) { + $image = str($database->image)->before(':')->value(); + switch ($image) { + case str($image)->contains('postgres'): + $userVariables = ['SERVICE_USER_POSTGRES', 'SERVICE_USER_POSTGRESQL']; + $passwordVariables = ['SERVICE_PASSWORD_POSTGRES', 'SERVICE_PASSWORD_POSTGRESQL']; + $dbNameVariables = ['POSTGRESQL_DATABASE', 'POSTGRES_DB']; + $postgres_user = $this->environment_variables()->whereIn('key', $userVariables)->first(); + $postgres_password = $this->environment_variables()->whereIn('key', $passwordVariables)->first(); + $postgres_db_name = $this->environment_variables()->whereIn('key', $dbNameVariables)->first(); + $fields->put('PostgreSQL', [ + 'User' => [ + 'key' => data_get($postgres_user, 'key'), + 'value' => data_get($postgres_user, 'value'), + 'rules' => 'required', + ], + 'Password' => [ + 'key' => data_get($postgres_password, 'key'), + 'value' => data_get($postgres_password, 'value'), + 'rules' => 'required', + 'isPassword' => true, + ], + 'Database Name' => [ + 'key' => data_get($postgres_db_name, 'key'), + 'value' => data_get($postgres_db_name, 'value'), + 'rules' => 'required', + ], + ]); + break; + case str($image)->contains('mysql'): + $userVariables = ['SERVICE_USER_MYSQL', 'SERVICE_USER_WORDPRESS']; + $passwordVariables = ['SERVICE_PASSWORD_MYSQL', 'SERVICE_PASSWORD_WORDPRESS']; + $rootPasswordVariables = ['SERVICE_PASSWORD_MYSQLROOT', 'SERVICE_PASSWORD_ROOT']; + $dbNameVariables = ['MYSQL_DATABASE']; + $mysql_user = $this->environment_variables()->whereIn('key', $userVariables)->first(); + $mysql_password = $this->environment_variables()->whereIn('key', $passwordVariables)->first(); + $mysql_root_password = $this->environment_variables()->whereIn('key', $rootPasswordVariables)->first(); + $mysql_db_name = $this->environment_variables()->whereIn('key', $dbNameVariables)->first(); + $fields->put('MySQL', [ + 'User' => [ + 'key' => data_get($mysql_user, 'key'), + 'value' => data_get($mysql_user, 'value'), + 'rules' => 'required', + ], + 'Password' => [ + 'key' => data_get($mysql_password, 'key'), + 'value' => data_get($mysql_password, 'value'), + 'rules' => 'required', + 'isPassword' => true, + ], + 'Root Password' => [ + 'key' => data_get($mysql_root_password, 'key'), + 'value' => data_get($mysql_root_password, 'value'), + 'rules' => 'required', + 'isPassword' => true, + ], + 'Database Name' => [ + 'key' => data_get($mysql_db_name, 'key'), + 'value' => data_get($mysql_db_name, 'value'), + 'rules' => 'required', + ], + ]); + break; + case str($image)->contains('mariadb'): + $userVariables = ['SERVICE_USER_MARIADB', 'SERVICE_USER_WORDPRESS', '_APP_DB_USER']; + $passwordVariables = ['SERVICE_PASSWORD_MARIADB', 'SERVICE_PASSWORD_WORDPRESS', '_APP_DB_PASS']; + $rootPasswordVariables = ['SERVICE_PASSWORD_MARIADBROOT', 'SERVICE_PASSWORD_ROOT', '_APP_DB_ROOT_PASS']; + $dbNameVariables = ['SERVICE_DATABASE_MARIADB', 'SERVICE_DATABASE_WORDPRESS', '_APP_DB_SCHEMA']; + $mariadb_user = $this->environment_variables()->whereIn('key', $userVariables)->first(); + $mariadb_password = $this->environment_variables()->whereIn('key', $passwordVariables)->first(); + $mariadb_root_password = $this->environment_variables()->whereIn('key', $rootPasswordVariables)->first(); + $mariadb_db_name = $this->environment_variables()->whereIn('key', $dbNameVariables)->first(); + $fields->put('MariaDB', [ + 'User' => [ + 'key' => data_get($mariadb_user, 'key'), + 'value' => data_get($mariadb_user, 'value'), + 'rules' => 'required', + ], + 'Password' => [ + 'key' => data_get($mariadb_password, 'key'), + 'value' => data_get($mariadb_password, 'value'), + 'rules' => 'required', + 'isPassword' => true, + ], + 'Root Password' => [ + 'key' => data_get($mariadb_root_password, 'key'), + 'value' => data_get($mariadb_root_password, 'value'), + 'rules' => 'required', + 'isPassword' => true, + ], + 'Database Name' => [ + 'key' => data_get($mariadb_db_name, 'key'), + 'value' => data_get($mariadb_db_name, 'value'), + 'rules' => data_get($mariadb_db_name, 'value') && 'required', + ], + ]); + + break; + } + } + return $fields; + } + public function saveExtraFields($fields) + { + foreach ($fields as $field) { + $key = data_get($field, 'key'); + $value = data_get($field, 'value'); + $found = $this->environment_variables()->where('key', $key)->first(); + if ($found) { + $found->value = $value; + $found->save(); + } else { + $this->environment_variables()->create([ + 'key' => $key, + 'value' => $value, + 'is_build_time' => false, + 'service_id' => $this->id, + 'is_preview' => false, + ]); + } + } + } public function documentation() { $services = getServiceTemplates(); @@ -257,7 +418,7 @@ class Service extends BaseModel } } $networks = collect(); - foreach ($serviceNetworks as $key =>$serviceNetwork) { + foreach ($serviceNetworks as $key => $serviceNetwork) { if (gettype($serviceNetwork) === 'string') { // networks: // - appwrite @@ -268,7 +429,7 @@ class Service extends BaseModel // ipv4_address: 192.168.203.254 // $networks->put($serviceNetwork, null); ray($key); - $networks->put($key,$serviceNetwork); + $networks->put($key, $serviceNetwork); } } foreach ($definedNetwork as $key => $network) { @@ -564,12 +725,18 @@ class Service extends BaseModel } // Add labels to the service - $fqdns = collect(data_get($savedService, 'fqdns')); - $defaultLabels = defaultLabels($this->id, $containerName, type: 'service', subType: $isDatabase ? 'database' : 'application', subId: $savedService->id); - $serviceLabels = $serviceLabels->merge($defaultLabels); - if (!$isDatabase && $fqdns->count() > 0) { - if ($fqdns) { - $serviceLabels = $serviceLabels->merge(fqdnLabelsForTraefik($this->uuid, $fqdns, true)); + if (!$isDatabase) { + if ($savedService->serviceType()) { + $fqdns = generateServiceSpecificFqdns($savedService, forTraefik: true); + } else { + $fqdns = collect(data_get($savedService, 'fqdns')); + } + $defaultLabels = defaultLabels($this->id, $containerName, type: 'service', subType: $isDatabase ? 'database' : 'application', subId: $savedService->id); + $serviceLabels = $serviceLabels->merge($defaultLabels); + if ($fqdns->count() > 0) { + if ($fqdns) { + $serviceLabels = $serviceLabels->merge(fqdnLabelsForTraefik($this->uuid, $fqdns, true)); + } } } data_set($service, 'labels', $serviceLabels->toArray()); diff --git a/app/Models/ServiceApplication.php b/app/Models/ServiceApplication.php index c70ceeccf..b1db1c581 100644 --- a/app/Models/ServiceApplication.php +++ b/app/Models/ServiceApplication.php @@ -22,6 +22,16 @@ class ServiceApplication extends BaseModel { return 'service'; } + public function serviceType() + { + $found = str(collect(SPECIFIC_SERVICES)->filter(function ($service) { + return str($this->image)->before(':')->value() === $service; + })->first()); + if ($found->isNotEmpty()) { + return $found; + } + return null; + } public function service() { return $this->belongsTo(Service::class); diff --git a/app/Models/ServiceDatabase.php b/app/Models/ServiceDatabase.php index 0dbbf6196..e37821af2 100644 --- a/app/Models/ServiceDatabase.php +++ b/app/Models/ServiceDatabase.php @@ -29,7 +29,6 @@ class ServiceDatabase extends BaseModel return "standalone-$image"; } public function getServiceDatabaseUrl() { - // $type = $this->databaseType(); $port = $this->public_port; $realIp = $this->service->server->ip; if ($realIp === 'host.docker.internal' || isDev()) { diff --git a/app/View/Components/Services/Links.php b/app/View/Components/Services/Links.php index b2cc8618d..b3953c174 100644 --- a/app/View/Components/Services/Links.php +++ b/app/View/Components/Services/Links.php @@ -16,22 +16,28 @@ class Links extends Component { $this->links = collect([]); $service->applications()->get()->map(function ($application) { - if ($application->fqdn) { - $fqdns = collect(Str::of($application->fqdn)->explode(',')); - $fqdns->map(function ($fqdn) { - $this->links->push(getFqdnWithoutPort($fqdn)); - }); - } - if ($application->ports) { - $portsCollection = collect(Str::of($application->ports)->explode(',')); - $portsCollection->map(function ($port) { - if (Str::of($port)->contains(':')) { - $hostPort = Str::of($port)->before(':'); - } else { - $hostPort = $port; - } - $this->links->push(base_url(withPort:false) . ":{$hostPort}"); - }); + $type = $application->serviceType(); + if ($type) { + $links = generateServiceSpecificFqdns($application, false); + $this->links = $this->links->merge($links); + } else { + if ($application->fqdn) { + $fqdns = collect(Str::of($application->fqdn)->explode(',')); + $fqdns->map(function ($fqdn) { + $this->links->push(getFqdnWithoutPort($fqdn)); + }); + } + if ($application->ports) { + $portsCollection = collect(Str::of($application->ports)->explode(',')); + $portsCollection->map(function ($port) { + if (Str::of($port)->contains(':')) { + $hostPort = Str::of($port)->before(':'); + } else { + $hostPort = $port; + } + $this->links->push(base_url(withPort: false) . ":{$hostPort}"); + }); + } } }); } diff --git a/bootstrap/helpers/constants.php b/bootstrap/helpers/constants.php index 10c1353d3..e844efea9 100644 --- a/bootstrap/helpers/constants.php +++ b/bootstrap/helpers/constants.php @@ -23,3 +23,6 @@ const DATABASE_DOCKER_IMAGES = [ 'influxdb', 'clickhouse/clickhouse-server' ]; +const SPECIFIC_SERVICES = [ + 'quay.io/minio/minio', +]; diff --git a/bootstrap/helpers/docker.php b/bootstrap/helpers/docker.php index 90c4179a7..7a92ab072 100644 --- a/bootstrap/helpers/docker.php +++ b/bootstrap/helpers/docker.php @@ -144,6 +144,39 @@ function defaultLabels($id, $name, $pull_request_id = 0, string $type = 'applica } return $labels; } +function generateServiceSpecificFqdns($service, $forTraefik = false) +{ + $variables = collect($service->service->environment_variables); + $type = $service->serviceType(); + $payload = collect([]); + switch ($type) { + case $type->contains('minio'): + $MINIO_BROWSER_REDIRECT_URL = $variables->where('key', 'MINIO_BROWSER_REDIRECT_URL')->first(); + if (is_null($MINIO_BROWSER_REDIRECT_URL?->value)) { + $MINIO_BROWSER_REDIRECT_URL->update([ + "value" => generateFqdn($service->service->server, 'console-' . $service->uuid) + ]); + } + $MINIO_SERVER_URL = $variables->where('key', 'MINIO_SERVER_URL')->first(); + if (is_null($MINIO_SERVER_URL?->value)) { + $MINIO_SERVER_URL->update([ + "value" => generateFqdn($service->service->server, 'minio-' . $service->uuid) + ]); + } + if ($forTraefik) { + $payload = collect([ + $MINIO_BROWSER_REDIRECT_URL->value . ':9001', + $MINIO_SERVER_URL->value . ':9000', + ]); + } else { + $payload = collect([ + $MINIO_BROWSER_REDIRECT_URL->value, + $MINIO_SERVER_URL->value, + ]); + } + } + return $payload; +} function fqdnLabelsForTraefik(string $uuid, Collection $domains, bool $is_force_https_enabled, $onlyPort = null) { $labels = collect([]); diff --git a/bootstrap/helpers/services.php b/bootstrap/helpers/services.php index b9a305a42..43a15444c 100644 --- a/bootstrap/helpers/services.php +++ b/bootstrap/helpers/services.php @@ -126,7 +126,6 @@ function getFilesystemVolumesFromServer(ServiceApplication|ServiceDatabase $oneS function updateCompose($resource) { try { - ray($resource); $name = data_get($resource, 'name'); $dockerComposeRaw = data_get($resource, 'service.docker_compose_raw'); $dockerCompose = Yaml::parse($dockerComposeRaw); diff --git a/bootstrap/helpers/shared.php b/bootstrap/helpers/shared.php index 013821bd7..d6766a8d0 100644 --- a/bootstrap/helpers/shared.php +++ b/bootstrap/helpers/shared.php @@ -27,7 +27,6 @@ use Illuminate\Support\Facades\Mail; use Illuminate\Support\Facades\Route; use Illuminate\Support\Str; use Illuminate\Support\Stringable; -use Nubs\RandomNameGenerator\All; use Poliander\Cron\CronExpression; use Visus\Cuid2\Cuid2; use phpseclib3\Crypt\RSA; @@ -173,7 +172,11 @@ function get_latest_version_of_coolify(): string function generate_random_name(?string $cuid = null): string { - $generator = All::create(); + $generator = new \Nubs\RandomNameGenerator\All( + [ + new \Nubs\RandomNameGenerator\Alliteration(), + ] + ); if (is_null($cuid)) { $cuid = new Cuid2(7); } @@ -444,20 +447,25 @@ function getServiceTemplates() if (isDev()) { $services = File::get(base_path('templates/service-templates.json')); $services = collect(json_decode($services))->sortKeys(); - $version = config('version'); - $services = $services->map(function ($service) use ($version) { - if (version_compare($version, data_get($service, 'minVersion', '0.0.0'), '<')) { - $service->disabled = true; - } - return $service; - }); } else { - $services = Http::get(config('constants.services.official')); - if ($services->failed()) { - throw new \Exception($services->body()); + try { + $response = Http::retry(3, 50)->get(config('constants.services.official')); + if ($response->failed()) { + return collect([]); + } + $services = $response->json(); + $services = collect($services)->sortKeys(); + } catch (\Throwable $e) { + $services = collect([]); } - $services = collect($services->json())->sortKeys(); } + // $version = config('version'); + // $services = $services->map(function ($service) use ($version) { + // if (version_compare($version, data_get($service, 'minVersion', '0.0.0'), '<')) { + // $service->disabled = true; + // } + // return $service; + // }); return $services; } @@ -493,7 +501,8 @@ function queryResourcesByUuid(string $uuid) return $resource; } -function generateDeployWebhook($resource) { +function generateDeployWebhook($resource) +{ $baseUrl = base_url(); $api = Url::fromString($baseUrl) . '/api/v1'; $endpoint = '/deploy'; @@ -501,6 +510,7 @@ function generateDeployWebhook($resource) { $url = $api . $endpoint . "?uuid=$uuid&force=false"; return $url; } -function removeAnsiColors($text) { +function removeAnsiColors($text) +{ return preg_replace('/\e[[][A-Za-z0-9];?[0-9]*m?/', '', $text); } diff --git a/config/sentry.php b/config/sentry.php index c889afb12..d52a8a9b4 100644 --- a/config/sentry.php +++ b/config/sentry.php @@ -7,7 +7,7 @@ return [ // The release version of your application // Example with dynamic git hash: trim(exec('git --git-dir ' . base_path('.git') . ' log --pretty="%h" -n1 HEAD')) - 'release' => '4.0.0-beta.123', + 'release' => '4.0.0-beta.124', // When left empty or `null` the Laravel environment will be used 'environment' => config('app.env'), diff --git a/config/version.php b/config/version.php index f31b19ca0..352ef7c4b 100644 --- a/config/version.php +++ b/config/version.php @@ -1,3 +1,3 @@ - +
@if (serviceStatus($service) === 'degraded') @endif @empty -
No service found.
+
No service found. Please try to reload the list!
@endforelse @endif diff --git a/resources/views/livewire/project/service/application.blade.php b/resources/views/livewire/project/service/application.blade.php index df09da467..db1329f81 100644 --- a/resources/views/livewire/project/service/application.blade.php +++ b/resources/views/livewire/project/service/application.blade.php @@ -16,19 +16,21 @@
- @if ($application->required_fqdn) - - @else - + @if (!$application->serviceType()?->contains(str($application->image)->before(':'))) + @if ($application->required_fqdn) + + @else + + @endif @endif
-

Advanced

-
+
@foreach ($applications as $application)
Str::of( @@ -58,7 +58,7 @@ @endif
{{ $application->status }}
- Logs
@@ -88,7 +88,7 @@ @endif
{{ $database->status }}
- Logs
diff --git a/resources/views/livewire/project/service/stack-form.blade.php b/resources/views/livewire/project/service/stack-form.blade.php index 7a6b7d808..1f6bd61ae 100644 --- a/resources/views/livewire/project/service/stack-form.blade.php +++ b/resources/views/livewire/project/service/stack-form.blade.php @@ -12,9 +12,17 @@
- {{-- @if ($isConfigurationRequired) -
This service requires additional confiugration. Please check our documentation for further information. + @if ($fields) +
+

Service Specific Configuration

- @endif --}} +
+ @foreach ($fields as $serviceName => $fields) + + @endforeach +
+ @endif diff --git a/templates/compose/fider.yaml b/templates/compose/fider.yaml index e2bf00910..b75ba68cd 100644 --- a/templates/compose/fider.yaml +++ b/templates/compose/fider.yaml @@ -1,4 +1,4 @@ -# documentation: https://fider.io/doc +# documentation: https://fider.io/docs # slogan: Fider is an open-source feedback platform for collecting and managing user feedback, helping you prioritize improvements to your products and services. # tags: feedback, user-feedback diff --git a/templates/compose/minio.yaml b/templates/compose/minio.yaml index 569172ca0..dcc68bc53 100644 --- a/templates/compose/minio.yaml +++ b/templates/compose/minio.yaml @@ -13,29 +13,3 @@ services: - MINIO_ROOT_PASSWORD=$SERVICE_PASSWORD_MINIO volumes: - minio-data:/data - -# services: -# minio: -# image: minio/minio -# command: server /data --address ":9000" --console-address ":9001" -# networks: -# - coolify -# environment: -# - MINIO_SERVER_URL=http://minio.65.21.189.27.sslip.io -# - MINIO_BROWSER_REDIRECT_URL=http://console.65.21.189.27.sslip.io -# - MINIO_BROWSER=on -# - MINIO_ROOT_USER=asd -# - MINIO_ROOT_PASSWORD=asdasdasd -# labels: -# - "traefik.enable=true" -# - "traefik.http.routers.minio-console.rule=Host(`console.65.21.189.27.sslip.io`)" -# - "traefik.http.routers.minio-console.entrypoints=http" -# - "traefik.http.routers.minio-console.service=minio-console" -# - "traefik.http.services.minio-console.loadbalancer.server.port=9001" -# - "traefik.http.routers.minio.rule=Host(`minio.65.21.189.27.sslip.io`)" -# - "traefik.http.routers.minio.entrypoints=http" -# - "traefik.http.routers.minio.service=minio" -# - "traefik.http.services.minio.loadbalancer.server.port=9000" -# networks: -# coolify: -# external: true diff --git a/templates/service-templates.json b/templates/service-templates.json index 34bf51787..d6f73cc20 100644 --- a/templates/service-templates.json +++ b/templates/service-templates.json @@ -132,7 +132,7 @@ ] }, "fider": { - "documentation": "https:\/\/fider.io\/doc", + "documentation": "https:\/\/fider.io\/docs", "slogan": "Fider is an open-source feedback platform for collecting and managing user feedback, helping you prioritize improvements to your products and services.", "compose": "c2VydmljZXM6CiAgZmlkZXI6CiAgICBpbWFnZTogJ2dldGZpZGVyL2ZpZGVyOnN0YWJsZScKICAgIGVudmlyb25tZW50OgogICAgICBCQVNFX1VSTDogJFNFUlZJQ0VfRlFETl9GSURFUgogICAgICBEQVRBQkFTRV9VUkw6ICdwb3N0Z3JlczovLyRTRVJWSUNFX1VTRVJfTVlTUUw6JFNFUlZJQ0VfUEFTU1dPUkRfTVlTUUxAZGF0YWJhc2U6NTQzMi9maWRlcj9zc2xtb2RlPWRpc2FibGUnCiAgICAgIEpXVF9TRUNSRVQ6ICRTRVJWSUNFX1BBU1NXT1JEXzY0X0ZJREVSCiAgICAgIEVNQUlMX05PUkVQTFk6ICcke0VNQUlMX05PUkVQTFk6LW5vcmVwbHlAZXhhbXBsZS5jb219JwogICAgICBFTUFJTF9NQUlMR1VOX0FQSTogJEVNQUlMX01BSUxHVU5fQVBJCiAgICAgIEVNQUlMX01BSUxHVU5fRE9NQUlOOiAkRU1BSUxfTUFJTEdVTl9ET01BSU4KICAgICAgRU1BSUxfTUFJTEdVTl9SRUdJT046ICRFTUFJTF9NQUlMR1VOX1JFR0lPTgogICAgICBFTUFJTF9TTVRQX0hPU1Q6ICcke0VNQUlMX1NNVFBfSE9TVDotc210cC5tYWlsZ3VuLmNvbX0nCiAgICAgIEVNQUlMX1NNVFBfUE9SVDogJyR7RU1BSUxfU01UUF9QT1JUOi01ODd9JwogICAgICBFTUFJTF9TTVRQX1VTRVJOQU1FOiAnJHtFTUFJTF9TTVRQX1VTRVJOQU1FOi1wb3N0bWFzdGVyQG1haWxndW4uY29tfScKICAgICAgRU1BSUxfU01UUF9QQVNTV09SRDogJEVNQUlMX1NNVFBfUEFTU1dPUkQKICAgICAgRU1BSUxfU01UUF9FTkFCTEVfU1RBUlRUTFM6ICRFTUFJTF9TTVRQX0VOQUJMRV9TVEFSVFRMUwogICAgICBFTUFJTF9BV1NTRVNfUkVHSU9OOiAkRU1BSUxfQVdTU0VTX1JFR0lPTgogICAgICBFTUFJTF9BV1NTRVNfQUNDRVNTX0tFWV9JRDogJEVNQUlMX0FXU1NFU19BQ0NFU1NfS0VZX0lECiAgICAgIEVNQUlMX0FXU1NFU19TRUNSRVRfQUNDRVNTX0tFWTogJEVNQUlMX0FXU1NFU19TRUNSRVRfQUNDRVNTX0tFWQogIGRhdGFiYXNlOgogICAgaW1hZ2U6ICdwb3N0Z3JlczoxMicKICAgIHZvbHVtZXM6CiAgICAgIC0gJ3BnX2RhdGE6L3Zhci9saWIvcG9zdGdyZXNxbC9kYXRhJwogICAgZW52aXJvbm1lbnQ6CiAgICAgIFBPU1RHUkVTX1VTRVI6ICRTRVJWSUNFX1VTRVJfTVlTUUwKICAgICAgUE9TVEdSRVNfUEFTU1dPUkQ6ICRTRVJWSUNFX1BBU1NXT1JEX01ZU1FMCiAgICAgIFBPU1RHUkVTX0RCOiAnJHtQT1NUR1JFU19EQjotZmlkZXJ9Jwo=", "tags": [ diff --git a/versions.json b/versions.json index c62fd27f5..4b4b2f731 100644 --- a/versions.json +++ b/versions.json @@ -4,7 +4,7 @@ "version": "3.12.36" }, "v4": { - "version": "4.0.0-beta.123" + "version": "4.0.0-beta.124" } } }