{{ $user->name }}
{{ $user->email }}
diff --git a/routes/api.php b/routes/api.php
index e8425aeb1..9ad64c40c 100644
--- a/routes/api.php
+++ b/routes/api.php
@@ -11,8 +11,6 @@ use App\Http\Controllers\Api\ServersController;
use App\Http\Controllers\Api\ServicesController;
use App\Http\Controllers\Api\TeamController;
use App\Http\Middleware\ApiAllowed;
-use App\Http\Middleware\IgnoreReadOnlyApiToken;
-use App\Http\Middleware\OnlyRootApiToken;
use App\Jobs\PushServerUpdateJob;
use App\Models\Server;
use Illuminate\Support\Facades\Route;
@@ -21,113 +19,113 @@ Route::get('/health', [OtherController::class, 'healthcheck']);
Route::post('/feedback', [OtherController::class, 'feedback']);
Route::group([
- 'middleware' => ['auth:sanctum', OnlyRootApiToken::class],
+ 'middleware' => ['auth:sanctum', 'api.ability:write'],
'prefix' => 'v1',
], function () {
Route::get('/enable', [OtherController::class, 'enable_api']);
Route::get('/disable', [OtherController::class, 'disable_api']);
});
Route::group([
- 'middleware' => ['auth:sanctum', ApiAllowed::class],
+ 'middleware' => ['auth:sanctum', ApiAllowed::class, 'api.sensitive'],
'prefix' => 'v1',
], function () {
- Route::get('/version', [OtherController::class, 'version']);
+ Route::get('/version', [OtherController::class, 'version'])->middleware(['api.ability:read']);
- Route::get('/teams', [TeamController::class, 'teams']);
- Route::get('/teams/current', [TeamController::class, 'current_team']);
- Route::get('/teams/current/members', [TeamController::class, 'current_team_members']);
- Route::get('/teams/{id}', [TeamController::class, 'team_by_id']);
- Route::get('/teams/{id}/members', [TeamController::class, 'members_by_id']);
+ Route::get('/teams', [TeamController::class, 'teams'])->middleware(['api.ability:read']);
+ Route::get('/teams/current', [TeamController::class, 'current_team'])->middleware(['api.ability:read']);
+ Route::get('/teams/current/members', [TeamController::class, 'current_team_members'])->middleware(['api.ability:read']);
+ Route::get('/teams/{id}', [TeamController::class, 'team_by_id'])->middleware(['api.ability:read']);
+ Route::get('/teams/{id}/members', [TeamController::class, 'members_by_id'])->middleware(['api.ability:read']);
- Route::get('/projects', [ProjectController::class, 'projects']);
- Route::get('/projects/{uuid}', [ProjectController::class, 'project_by_uuid']);
- Route::get('/projects/{uuid}/{environment_name}', [ProjectController::class, 'environment_details']);
+ Route::get('/projects', [ProjectController::class, 'projects'])->middleware(['api.ability:read']);
+ Route::get('/projects/{uuid}', [ProjectController::class, 'project_by_uuid'])->middleware(['api.ability:read']);
+ Route::get('/projects/{uuid}/{environment_name}', [ProjectController::class, 'environment_details'])->middleware(['api.ability:read']);
- Route::post('/projects', [ProjectController::class, 'create_project']);
- Route::patch('/projects/{uuid}', [ProjectController::class, 'update_project']);
- Route::delete('/projects/{uuid}', [ProjectController::class, 'delete_project']);
+ Route::post('/projects', [ProjectController::class, 'create_project'])->middleware(['api.ability:read']);
+ Route::patch('/projects/{uuid}', [ProjectController::class, 'update_project'])->middleware(['api.ability:write']);
+ Route::delete('/projects/{uuid}', [ProjectController::class, 'delete_project'])->middleware(['api.ability:write']);
- Route::get('/security/keys', [SecurityController::class, 'keys']);
- Route::post('/security/keys', [SecurityController::class, 'create_key'])->middleware([IgnoreReadOnlyApiToken::class]);
+ Route::get('/security/keys', [SecurityController::class, 'keys'])->middleware(['api.ability:read']);
+ Route::post('/security/keys', [SecurityController::class, 'create_key'])->middleware(['api.ability:write']);
- Route::get('/security/keys/{uuid}', [SecurityController::class, 'key_by_uuid']);
- Route::patch('/security/keys/{uuid}', [SecurityController::class, 'update_key'])->middleware([IgnoreReadOnlyApiToken::class]);
- Route::delete('/security/keys/{uuid}', [SecurityController::class, 'delete_key'])->middleware([IgnoreReadOnlyApiToken::class]);
+ Route::get('/security/keys/{uuid}', [SecurityController::class, 'key_by_uuid'])->middleware(['api.ability:read']);
+ Route::patch('/security/keys/{uuid}', [SecurityController::class, 'update_key'])->middleware(['api.ability:write']);
+ Route::delete('/security/keys/{uuid}', [SecurityController::class, 'delete_key'])->middleware(['api.ability:write']);
- Route::match(['get', 'post'], '/deploy', [DeployController::class, 'deploy'])->middleware([IgnoreReadOnlyApiToken::class]);
- Route::get('/deployments', [DeployController::class, 'deployments']);
- Route::get('/deployments/{uuid}', [DeployController::class, 'deployment_by_uuid']);
+ Route::match(['get', 'post'], '/deploy', [DeployController::class, 'deploy'])->middleware(['api.ability:write,deploy']);
+ Route::get('/deployments', [DeployController::class, 'deployments'])->middleware(['api.ability:read']);
+ Route::get('/deployments/{uuid}', [DeployController::class, 'deployment_by_uuid'])->middleware(['api.ability:read']);
- Route::get('/servers', [ServersController::class, 'servers']);
- Route::get('/servers/{uuid}', [ServersController::class, 'server_by_uuid']);
- Route::get('/servers/{uuid}/domains', [ServersController::class, 'domains_by_server']);
- Route::get('/servers/{uuid}/resources', [ServersController::class, 'resources_by_server']);
+ Route::get('/servers', [ServersController::class, 'servers'])->middleware(['api.ability:read']);
+ Route::get('/servers/{uuid}', [ServersController::class, 'server_by_uuid'])->middleware(['api.ability:read']);
+ Route::get('/servers/{uuid}/domains', [ServersController::class, 'domains_by_server'])->middleware(['api.ability:read']);
+ Route::get('/servers/{uuid}/resources', [ServersController::class, 'resources_by_server'])->middleware(['api.ability:read']);
- Route::get('/servers/{uuid}/validate', [ServersController::class, 'validate_server']);
+ Route::get('/servers/{uuid}/validate', [ServersController::class, 'validate_server'])->middleware(['api.ability:read']);
- Route::post('/servers', [ServersController::class, 'create_server']);
- Route::patch('/servers/{uuid}', [ServersController::class, 'update_server']);
- Route::delete('/servers/{uuid}', [ServersController::class, 'delete_server']);
+ Route::post('/servers', [ServersController::class, 'create_server'])->middleware(['api.ability:read']);
+ Route::patch('/servers/{uuid}', [ServersController::class, 'update_server'])->middleware(['api.ability:write']);
+ Route::delete('/servers/{uuid}', [ServersController::class, 'delete_server'])->middleware(['api.ability:write']);
- Route::get('/resources', [ResourcesController::class, 'resources']);
+ Route::get('/resources', [ResourcesController::class, 'resources'])->middleware(['api.ability:read']);
- Route::get('/applications', [ApplicationsController::class, 'applications']);
- Route::post('/applications/public', [ApplicationsController::class, 'create_public_application'])->middleware([IgnoreReadOnlyApiToken::class]);
- Route::post('/applications/private-github-app', [ApplicationsController::class, 'create_private_gh_app_application'])->middleware([IgnoreReadOnlyApiToken::class]);
- Route::post('/applications/private-deploy-key', [ApplicationsController::class, 'create_private_deploy_key_application'])->middleware([IgnoreReadOnlyApiToken::class]);
- Route::post('/applications/dockerfile', [ApplicationsController::class, 'create_dockerfile_application'])->middleware([IgnoreReadOnlyApiToken::class]);
- Route::post('/applications/dockerimage', [ApplicationsController::class, 'create_dockerimage_application'])->middleware([IgnoreReadOnlyApiToken::class]);
- Route::post('/applications/dockercompose', [ApplicationsController::class, 'create_dockercompose_application'])->middleware([IgnoreReadOnlyApiToken::class]);
+ Route::get('/applications', [ApplicationsController::class, 'applications'])->middleware(['api.ability:read']);
+ Route::post('/applications/public', [ApplicationsController::class, 'create_public_application'])->middleware(['api.ability:write']);
+ Route::post('/applications/private-github-app', [ApplicationsController::class, 'create_private_gh_app_application'])->middleware(['api.ability:write']);
+ Route::post('/applications/private-deploy-key', [ApplicationsController::class, 'create_private_deploy_key_application'])->middleware(['api.ability:write']);
+ Route::post('/applications/dockerfile', [ApplicationsController::class, 'create_dockerfile_application'])->middleware(['api.ability:write']);
+ Route::post('/applications/dockerimage', [ApplicationsController::class, 'create_dockerimage_application'])->middleware(['api.ability:write']);
+ Route::post('/applications/dockercompose', [ApplicationsController::class, 'create_dockercompose_application'])->middleware(['api.ability:write']);
- Route::get('/applications/{uuid}', [ApplicationsController::class, 'application_by_uuid']);
- Route::patch('/applications/{uuid}', [ApplicationsController::class, 'update_by_uuid'])->middleware([IgnoreReadOnlyApiToken::class]);
- Route::delete('/applications/{uuid}', [ApplicationsController::class, 'delete_by_uuid'])->middleware([IgnoreReadOnlyApiToken::class]);
+ Route::get('/applications/{uuid}', [ApplicationsController::class, 'application_by_uuid'])->middleware(['api.ability:read']);
+ Route::patch('/applications/{uuid}', [ApplicationsController::class, 'update_by_uuid'])->middleware(['api.ability:write']);
+ Route::delete('/applications/{uuid}', [ApplicationsController::class, 'delete_by_uuid'])->middleware(['api.ability:write']);
- Route::get('/applications/{uuid}/envs', [ApplicationsController::class, 'envs']);
- Route::post('/applications/{uuid}/envs', [ApplicationsController::class, 'create_env'])->middleware([IgnoreReadOnlyApiToken::class]);
- Route::patch('/applications/{uuid}/envs/bulk', [ApplicationsController::class, 'create_bulk_envs'])->middleware([IgnoreReadOnlyApiToken::class]);
- Route::patch('/applications/{uuid}/envs', [ApplicationsController::class, 'update_env_by_uuid'])->middleware([IgnoreReadOnlyApiToken::class]);
- Route::delete('/applications/{uuid}/envs/{env_uuid}', [ApplicationsController::class, 'delete_env_by_uuid'])->middleware([IgnoreReadOnlyApiToken::class]);
- // Route::post('/applications/{uuid}/execute', [ApplicationsController::class, 'execute_command_by_uuid'])->middleware([OnlyRootApiToken::class]);
+ Route::get('/applications/{uuid}/envs', [ApplicationsController::class, 'envs'])->middleware(['api.ability:read']);
+ Route::post('/applications/{uuid}/envs', [ApplicationsController::class, 'create_env'])->middleware(['api.ability:write']);
+ Route::patch('/applications/{uuid}/envs/bulk', [ApplicationsController::class, 'create_bulk_envs'])->middleware(['api.ability:write']);
+ Route::patch('/applications/{uuid}/envs', [ApplicationsController::class, 'update_env_by_uuid'])->middleware(['api.ability:write']);
+ Route::delete('/applications/{uuid}/envs/{env_uuid}', [ApplicationsController::class, 'delete_env_by_uuid'])->middleware(['api.ability:write']);
+ // Route::post('/applications/{uuid}/execute', [ApplicationsController::class, 'execute_command_by_uuid'])->middleware(['ability:write']);
- Route::match(['get', 'post'], '/applications/{uuid}/start', [ApplicationsController::class, 'action_deploy'])->middleware([IgnoreReadOnlyApiToken::class]);
- Route::match(['get', 'post'], '/applications/{uuid}/restart', [ApplicationsController::class, 'action_restart'])->middleware([IgnoreReadOnlyApiToken::class]);
- Route::match(['get', 'post'], '/applications/{uuid}/stop', [ApplicationsController::class, 'action_stop'])->middleware([IgnoreReadOnlyApiToken::class]);
+ Route::match(['get', 'post'], '/applications/{uuid}/start', [ApplicationsController::class, 'action_deploy'])->middleware(['api.ability:write']);
+ Route::match(['get', 'post'], '/applications/{uuid}/restart', [ApplicationsController::class, 'action_restart'])->middleware(['api.ability:write']);
+ Route::match(['get', 'post'], '/applications/{uuid}/stop', [ApplicationsController::class, 'action_stop'])->middleware(['api.ability:write']);
- Route::get('/databases', [DatabasesController::class, 'databases']);
- Route::post('/databases/postgresql', [DatabasesController::class, 'create_database_postgresql'])->middleware([IgnoreReadOnlyApiToken::class]);
- Route::post('/databases/mysql', [DatabasesController::class, 'create_database_mysql'])->middleware([IgnoreReadOnlyApiToken::class]);
- Route::post('/databases/mariadb', [DatabasesController::class, 'create_database_mariadb'])->middleware([IgnoreReadOnlyApiToken::class]);
- Route::post('/databases/mongodb', [DatabasesController::class, 'create_database_mongodb'])->middleware([IgnoreReadOnlyApiToken::class]);
- Route::post('/databases/redis', [DatabasesController::class, 'create_database_redis'])->middleware([IgnoreReadOnlyApiToken::class]);
- Route::post('/databases/clickhouse', [DatabasesController::class, 'create_database_clickhouse'])->middleware([IgnoreReadOnlyApiToken::class]);
- Route::post('/databases/dragonfly', [DatabasesController::class, 'create_database_dragonfly'])->middleware([IgnoreReadOnlyApiToken::class]);
- Route::post('/databases/keydb', [DatabasesController::class, 'create_database_keydb'])->middleware([IgnoreReadOnlyApiToken::class]);
+ Route::get('/databases', [DatabasesController::class, 'databases'])->middleware(['api.ability:read']);
+ Route::post('/databases/postgresql', [DatabasesController::class, 'create_database_postgresql'])->middleware(['api.ability:write']);
+ Route::post('/databases/mysql', [DatabasesController::class, 'create_database_mysql'])->middleware(['api.ability:write']);
+ Route::post('/databases/mariadb', [DatabasesController::class, 'create_database_mariadb'])->middleware(['api.ability:write']);
+ Route::post('/databases/mongodb', [DatabasesController::class, 'create_database_mongodb'])->middleware(['api.ability:write']);
+ Route::post('/databases/redis', [DatabasesController::class, 'create_database_redis'])->middleware(['api.ability:write']);
+ Route::post('/databases/clickhouse', [DatabasesController::class, 'create_database_clickhouse'])->middleware(['api.ability:write']);
+ Route::post('/databases/dragonfly', [DatabasesController::class, 'create_database_dragonfly'])->middleware(['api.ability:write']);
+ Route::post('/databases/keydb', [DatabasesController::class, 'create_database_keydb'])->middleware(['api.ability:write']);
- Route::get('/databases/{uuid}', [DatabasesController::class, 'database_by_uuid']);
- Route::patch('/databases/{uuid}', [DatabasesController::class, 'update_by_uuid'])->middleware([IgnoreReadOnlyApiToken::class]);
- Route::delete('/databases/{uuid}', [DatabasesController::class, 'delete_by_uuid'])->middleware([IgnoreReadOnlyApiToken::class]);
+ Route::get('/databases/{uuid}', [DatabasesController::class, 'database_by_uuid'])->middleware(['api.ability:read']);
+ Route::patch('/databases/{uuid}', [DatabasesController::class, 'update_by_uuid'])->middleware(['api.ability:write']);
+ Route::delete('/databases/{uuid}', [DatabasesController::class, 'delete_by_uuid'])->middleware(['api.ability:write']);
- Route::match(['get', 'post'], '/databases/{uuid}/start', [DatabasesController::class, 'action_deploy'])->middleware([IgnoreReadOnlyApiToken::class]);
- Route::match(['get', 'post'], '/databases/{uuid}/restart', [DatabasesController::class, 'action_restart'])->middleware([IgnoreReadOnlyApiToken::class]);
- Route::match(['get', 'post'], '/databases/{uuid}/stop', [DatabasesController::class, 'action_stop'])->middleware([IgnoreReadOnlyApiToken::class]);
+ Route::match(['get', 'post'], '/databases/{uuid}/start', [DatabasesController::class, 'action_deploy'])->middleware(['api.ability:write']);
+ Route::match(['get', 'post'], '/databases/{uuid}/restart', [DatabasesController::class, 'action_restart'])->middleware(['api.ability:write']);
+ Route::match(['get', 'post'], '/databases/{uuid}/stop', [DatabasesController::class, 'action_stop'])->middleware(['api.ability:write']);
- Route::get('/services', [ServicesController::class, 'services']);
- Route::post('/services', [ServicesController::class, 'create_service'])->middleware([IgnoreReadOnlyApiToken::class]);
+ Route::get('/services', [ServicesController::class, 'services'])->middleware(['api.ability:read']);
+ Route::post('/services', [ServicesController::class, 'create_service'])->middleware(['api.ability:write']);
- Route::get('/services/{uuid}', [ServicesController::class, 'service_by_uuid']);
- // Route::patch('/services/{uuid}', [ServicesController::class, 'update_by_uuid'])->middleware([IgnoreReadOnlyApiToken::class]);
- Route::delete('/services/{uuid}', [ServicesController::class, 'delete_by_uuid'])->middleware([IgnoreReadOnlyApiToken::class]);
+ Route::get('/services/{uuid}', [ServicesController::class, 'service_by_uuid'])->middleware(['api.ability:read']);
+ // Route::patch('/services/{uuid}', [ServicesController::class, 'update_by_uuid'])->middleware(['ability:write']);
+ Route::delete('/services/{uuid}', [ServicesController::class, 'delete_by_uuid'])->middleware(['api.ability:write']);
- Route::get('/services/{uuid}/envs', [ServicesController::class, 'envs']);
- Route::post('/services/{uuid}/envs', [ServicesController::class, 'create_env'])->middleware([IgnoreReadOnlyApiToken::class]);
- Route::patch('/services/{uuid}/envs/bulk', [ServicesController::class, 'create_bulk_envs'])->middleware([IgnoreReadOnlyApiToken::class]);
- Route::patch('/services/{uuid}/envs', [ServicesController::class, 'update_env_by_uuid'])->middleware([IgnoreReadOnlyApiToken::class]);
- Route::delete('/services/{uuid}/envs/{env_uuid}', [ServicesController::class, 'delete_env_by_uuid'])->middleware([IgnoreReadOnlyApiToken::class]);
+ Route::get('/services/{uuid}/envs', [ServicesController::class, 'envs'])->middleware(['api.ability:read']);
+ Route::post('/services/{uuid}/envs', [ServicesController::class, 'create_env'])->middleware(['api.ability:write']);
+ Route::patch('/services/{uuid}/envs/bulk', [ServicesController::class, 'create_bulk_envs'])->middleware(['api.ability:write']);
+ Route::patch('/services/{uuid}/envs', [ServicesController::class, 'update_env_by_uuid'])->middleware(['api.ability:write']);
+ Route::delete('/services/{uuid}/envs/{env_uuid}', [ServicesController::class, 'delete_env_by_uuid'])->middleware(['api.ability:write']);
- Route::match(['get', 'post'], '/services/{uuid}/start', [ServicesController::class, 'action_deploy'])->middleware([IgnoreReadOnlyApiToken::class]);
- Route::match(['get', 'post'], '/services/{uuid}/restart', [ServicesController::class, 'action_restart'])->middleware([IgnoreReadOnlyApiToken::class]);
- Route::match(['get', 'post'], '/services/{uuid}/stop', [ServicesController::class, 'action_stop'])->middleware([IgnoreReadOnlyApiToken::class]);
+ Route::match(['get', 'post'], '/services/{uuid}/start', [ServicesController::class, 'action_deploy'])->middleware(['api.ability:write']);
+ Route::match(['get', 'post'], '/services/{uuid}/restart', [ServicesController::class, 'action_restart'])->middleware(['api.ability:write']);
+ Route::match(['get', 'post'], '/services/{uuid}/stop', [ServicesController::class, 'action_stop'])->middleware(['api.ability:write']);
});
Route::group([
diff --git a/routes/web.php b/routes/web.php
index e90bbfac7..f7bec5be5 100644
--- a/routes/web.php
+++ b/routes/web.php
@@ -12,6 +12,7 @@ use App\Livewire\Destination\Show as DestinationShow;
use App\Livewire\ForcePasswordReset;
use App\Livewire\Notifications\Discord as NotificationDiscord;
use App\Livewire\Notifications\Email as NotificationEmail;
+use App\Livewire\Notifications\Slack as NotificationSlack;
use App\Livewire\Notifications\Telegram as NotificationTelegram;
use App\Livewire\Profile\Index as ProfileIndex;
use App\Livewire\Project\Application\Configuration as ApplicationConfiguration;
@@ -132,6 +133,7 @@ Route::middleware(['auth', 'verified'])->group(function () {
Route::get('/email', NotificationEmail::class)->name('notifications.email');
Route::get('/telegram', NotificationTelegram::class)->name('notifications.telegram');
Route::get('/discord', NotificationDiscord::class)->name('notifications.discord');
+ Route::get('/slack', NotificationSlack::class)->name('notifications.slack');
});
Route::prefix('storages')->group(function () {
diff --git a/scripts/install.sh b/scripts/install.sh
index 1a039f64f..3f289438f 100755
--- a/scripts/install.sh
+++ b/scripts/install.sh
@@ -30,7 +30,7 @@ WARNING_SPACE=false
if [ "$TOTAL_SPACE" -lt "$REQUIRED_TOTAL_SPACE" ]; then
WARNING_SPACE=true
- cat << 'EOF'
+ cat << EOF
WARNING: Insufficient total disk space!
Total disk space: ${TOTAL_SPACE}GB
@@ -41,7 +41,7 @@ EOF
fi
if [ "$AVAILABLE_SPACE" -lt "$REQUIRED_AVAILABLE_SPACE" ]; then
- cat << 'EOF'
+ cat << EOF
WARNING: Insufficient available disk space!
Available disk space: ${AVAILABLE_SPACE}GB
@@ -49,7 +49,7 @@ Required available space: ${REQUIRED_AVAILABLE_SPACE}GB
==================
EOF
- WARNING_SPACE=true
+WARNING_SPACE=true
fi
if [ "$WARNING_SPACE" = true ]; then
diff --git a/templates/compose/heimdall.yaml b/templates/compose/heimdall.yaml
index 7ae07b296..851f981b5 100644
--- a/templates/compose/heimdall.yaml
+++ b/templates/compose/heimdall.yaml
@@ -1,6 +1,7 @@
# documentation: https://github.com/linuxserver/Heimdall
# slogan: Heimdall is a dashboard for managing and organizing your server applications.
# tags: dashboard, server, applications, interface
+# logo: svgs/heimdall.svg
services:
heimdall:
diff --git a/templates/compose/invoice-ninja.yaml b/templates/compose/invoice-ninja.yaml
index 9a767126b..beb05d983 100644
--- a/templates/compose/invoice-ninja.yaml
+++ b/templates/compose/invoice-ninja.yaml
@@ -1,6 +1,7 @@
# documentation: https://invoiceninja.github.io/selfhost.html
# slogan: The leading open-source invoicing platform
# tags: invoicing, billing, accounting, finance, self-hosted
+# logo: svgs/invoiceninja.png
# port: 9000
services:
diff --git a/templates/compose/kuzzle.yaml b/templates/compose/kuzzle.yaml
index f0ceaee68..a195cc600 100644
--- a/templates/compose/kuzzle.yaml
+++ b/templates/compose/kuzzle.yaml
@@ -1,6 +1,7 @@
# documentation: https://kuzzle.io
# slogan: Kuzzle is a generic backend offering the basic building blocks common to every application.
# tags: backend, api, realtime, websocket, mqtt, rest, sdk, iot, geofencing, low-code
+# logo: svgs/kuzzle.png
# port: 7512
services:
diff --git a/templates/compose/pairdrop.yaml b/templates/compose/pairdrop.yaml
index 44bac7000..3e71e8b84 100644
--- a/templates/compose/pairdrop.yaml
+++ b/templates/compose/pairdrop.yaml
@@ -1,6 +1,7 @@
# documentation: https://pairdrop.net/
# slogan: Pairdrop is a self-hosted file sharing and collaboration platform, offering secure file sharing and collaboration capabilities for efficient teamwork.
# tags: file, sharing, collaboration, teamwork
+# logo: svgs/pairdrop.png
# port: 3000
services:
diff --git a/templates/compose/penpot.yaml b/templates/compose/penpot.yaml
index 9bc21b398..05b73cdca 100644
--- a/templates/compose/penpot.yaml
+++ b/templates/compose/penpot.yaml
@@ -1,6 +1,7 @@
# documentation: https://help.penpot.app/technical-guide/getting-started/#install-with-docker
# slogan: Penpot is the first Open Source design and prototyping platform for product teams.
# tags: penpot,design,prototyping,figma,open,source
+# logo: svgs/penpot.svg
services:
frontend:
diff --git a/templates/compose/postiz.yaml b/templates/compose/postiz.yaml
index 503d0f67e..6060fb8a6 100644
--- a/templates/compose/postiz.yaml
+++ b/templates/compose/postiz.yaml
@@ -35,6 +35,7 @@ services:
- RESEND_API_KEY=${RESEND_API_KEY}
- EMAIL_FROM_ADDRESS=${EMAIL_FROM_ADDRESS}
- EMAIL_FROM_NAME=${EMAIL_FROM_NAME}
+ - EMAIL_PROVIDER=${EMAIL_PROVIDER}
# Social Media API Settings
- X_API_KEY=${SERVICE_X_API}
diff --git a/templates/compose/whoogle.yaml b/templates/compose/whoogle.yaml
index c049dac47..0be303f9a 100644
--- a/templates/compose/whoogle.yaml
+++ b/templates/compose/whoogle.yaml
@@ -1,6 +1,7 @@
# documentation: https://github.com/benbusby/whoogle-search?tab=readme-ov-file
# slogan: Whoogle is a self-hosted, privacy-focused search engine front-end for accessing Google search results without tracking and data collection.
# tags: privacy, search engine
+# logo: svgs/whoogle.png
# port: 5000
services:
diff --git a/templates/service-templates.json b/templates/service-templates.json
index 2e1e3bbf9..34da885d5 100644
--- a/templates/service-templates.json
+++ b/templates/service-templates.json
@@ -1125,7 +1125,7 @@
"applications",
"interface"
],
- "logo": "svgs/default.webp",
+ "logo": "svgs/heimdall.svg",
"minversion": "0.0.0"
},
"heyform": {
@@ -1251,7 +1251,7 @@
"finance",
"self-hosted"
],
- "logo": "svgs/default.webp",
+ "logo": "svgs/invoiceninja.png",
"minversion": "0.0.0",
"port": "9000"
},
@@ -1417,7 +1417,7 @@
"geofencing",
"low-code"
],
- "logo": "svgs/default.webp",
+ "logo": "svgs/kuzzle.png",
"minversion": "0.0.0",
"port": "7512"
},
@@ -2112,7 +2112,7 @@
"collaboration",
"teamwork"
],
- "logo": "svgs/default.webp",
+ "logo": "svgs/pairdrop.png",
"minversion": "0.0.0",
"port": "3000"
},
@@ -2137,7 +2137,7 @@
"open",
"source"
],
- "logo": "svgs/default.webp",
+ "logo": "svgs/penpot.svg",
"minversion": "0.0.0"
},
"phpmyadmin": {
@@ -2245,7 +2245,7 @@
"postiz": {
"documentation": "https://docs.postiz.com?utm_source=coolify.io",
"slogan": "Open source social media scheduling tool.",
- "compose": "c2VydmljZXM6CiAgcG9zdGl6OgogICAgaW1hZ2U6ICdnaGNyLmlvL2dpdHJvb21ocS9wb3N0aXotYXBwOmxhdGVzdCcKICAgIGVudmlyb25tZW50OgogICAgICAtIFNFUlZJQ0VfRlFETl9QT1NUSVpfNTAwMAogICAgICAtICdNQUlOX1VSTD0ke1NFUlZJQ0VfRlFETl9QT1NUSVp9JwogICAgICAtICdGUk9OVEVORF9VUkw9JHtTRVJWSUNFX0ZRRE5fUE9TVElafScKICAgICAgLSAnTkVYVF9QVUJMSUNfQkFDS0VORF9VUkw9JHtTRVJWSUNFX0ZRRE5fUE9TVElafS9hcGknCiAgICAgIC0gJ0pXVF9TRUNSRVQ9JHtTRVJWSUNFX1BBU1NXT1JEX0pXVFNFQ1JFVH0nCiAgICAgIC0gJ0RBVEFCQVNFX1VSTD1wb3N0Z3Jlc3FsOi8vcG9zdGdyZXM6JHtTRVJWSUNFX1BBU1NXT1JEX1BPU1RHUkVTUUx9QHBvc3RncmVzOjU0MzIvJHtQT1NUR1JFU1FMX0RBVEFCQVNFOi1wb3N0aXotZGJ9JwogICAgICAtICdSRURJU19VUkw9cmVkaXM6Ly9kZWZhdWx0OiR7U0VSVklDRV9QQVNTV09SRF9SRURJU31AcmVkaXM6NjM3OScKICAgICAgLSAnQkFDS0VORF9JTlRFUk5BTF9VUkw9aHR0cDovL2xvY2FsaG9zdDozMDAwJwogICAgICAtICdDTE9VREZMQVJFX0FDQ09VTlRfSUQ9JHtDTE9VREZMQVJFX0FDQ09VTlRfSUR9JwogICAgICAtICdDTE9VREZMQVJFX0FDQ0VTU19LRVk9JHtDTE9VREZMQVJFX0FDQ0VTU19LRVl9JwogICAgICAtICdDTE9VREZMQVJFX1NFQ1JFVF9BQ0NFU1NfS0VZPSR7Q0xPVURGTEFSRV9TRUNSRVRfQUNDRVNTX0tFWX0nCiAgICAgIC0gJ0NMT1VERkxBUkVfQlVDS0VUTkFNRT0ke0NMT1VERkxBUkVfQlVDS0VUTkFNRX0nCiAgICAgIC0gJ0NMT1VERkxBUkVfQlVDS0VUX1VSTD0ke0NMT1VERkxBUkVfQlVDS0VUX1VSTH0nCiAgICAgIC0gJ0NMT1VERkxBUkVfUkVHSU9OPSR7Q0xPVURGTEFSRV9SRUdJT059JwogICAgICAtICdTVE9SQUdFX1BST1ZJREVSPSR7U1RPUkFHRV9QUk9WSURFUjotbG9jYWx9JwogICAgICAtICdVUExPQURfRElSRUNUT1JZPSR7VVBMT0FEX0RJUkVDVE9SWTotL3VwbG9hZHN9JwogICAgICAtICdORVhUX1BVQkxJQ19VUExPQURfRElSRUNUT1JZPSR7TkVYVF9QVUJMSUNfVVBMT0FEX0RJUkVDVE9SWTotL3VwbG9hZHN9JwogICAgICAtICdORVhUX1BVQkxJQ19VUExPQURfU1RBVElDX0RJUkVDVE9SWT0ke05FWFRfUFVCTElDX1VQTE9BRF9TVEFUSUNfRElSRUNUT1JZfScKICAgICAgLSAnUkVTRU5EX0FQSV9LRVk9JHtSRVNFTkRfQVBJX0tFWX0nCiAgICAgIC0gJ0VNQUlMX0ZST01fQUREUkVTUz0ke0VNQUlMX0ZST01fQUREUkVTU30nCiAgICAgIC0gJ0VNQUlMX0ZST01fTkFNRT0ke0VNQUlMX0ZST01fTkFNRX0nCiAgICAgIC0gJ1hfQVBJX0tFWT0ke1NFUlZJQ0VfWF9BUEl9JwogICAgICAtICdYX0FQSV9TRUNSRVQ9JHtTRVJWSUNFX1hfU0VDUkVUfScKICAgICAgLSAnTElOS0VESU5fQ0xJRU5UX0lEPSR7U0VSVklDRV9MSU5LRURJTl9JRH0nCiAgICAgIC0gJ0xJTktFRElOX0NMSUVOVF9TRUNSRVQ9JHtTRVJWSUNFX0xJTktFRElOX1NFQ1JFVH0nCiAgICAgIC0gJ1JFRERJVF9DTElFTlRfSUQ9JHtTRVJWSUNFX1JFRERJVF9BUEl9JwogICAgICAtICdSRURESVRfQ0xJRU5UX1NFQ1JFVD0ke1NFUlZJQ0VfUkVERElUX1NFQ1JFVH0nCiAgICAgIC0gJ0dJVEhVQl9DTElFTlRfSUQ9JHtTRVJWSUNFX0dJVEhVQl9JRH0nCiAgICAgIC0gJ0dJVEhVQl9DTElFTlRfU0VDUkVUPSR7U0VSVklDRV9HSVRIVUJfU0VDUkVUfScKICAgICAgLSAnVEhSRUFEU19BUFBfSUQ9JHtTRVJWSUNFX1RIUkVBRFNfSUR9JwogICAgICAtICdUSFJFQURTX0FQUF9TRUNSRVQ9JHtTRVJWSUNFX1RIUkVBRFNfU0VDUkVUfScKICAgICAgLSAnRkFDRUJPT0tfQVBQX0lEPSR7U0VSVklDRV9GQUNFQk9PS19JRH0nCiAgICAgIC0gJ0ZBQ0VCT09LX0FQUF9TRUNSRVQ9JHtTRVJWSUNFX0ZBQ0VCT09LX1NFQ1JFVH0nCiAgICAgIC0gJ1lPVVRVQkVfQ0xJRU5UX0lEPSR7U0VSVklDRV9ZT1VUVUJFX0lEfScKICAgICAgLSAnWU9VVFVCRV9DTElFTlRfU0VDUkVUPSR7U0VSVklDRV9ZT1VUVUJFX1NFQ1JFVH0nCiAgICAgIC0gJ1RJS1RPS19DTElFTlRfSUQ9JHtTRVJWSUNFX1RJS1RPS19JRH0nCiAgICAgIC0gJ1RJS1RPS19DTElFTlRfU0VDUkVUPSR7U0VSVklDRV9USUtUT0tfU0VDUkVUfScKICAgICAgLSAnUElOVEVSRVNUX0NMSUVOVF9JRD0ke1NFUlZJQ0VfUElOVEVSRVNUX0lEfScKICAgICAgLSAnUElOVEVSRVNUX0NMSUVOVF9TRUNSRVQ9JHtTRVJWSUNFX1BJTlRFUkVTVF9TRUNSRVR9JwogICAgICAtICdEUklCQkJMRV9DTElFTlRfSUQ9JHtTRVJWSUNFX0RSSUJCTEVfSUR9JwogICAgICAtICdEUklCQkJMRV9DTElFTlRfU0VDUkVUPSR7U0VSVklDRV9EUklCQkxFX1NFQ1JFVH0nCiAgICAgIC0gJ0RJU0NPUkRfQ0xJRU5UX0lEPSR7U0VSVklDRV9ESVNDT1JEX0lEfScKICAgICAgLSAnRElTQ09SRF9DTElFTlRfU0VDUkVUPSR7U0VSVklDRV9ESVNDT1JEX1NFQ1JFVH0nCiAgICAgIC0gJ0RJU0NPUkRfQk9UX1RPS0VOX0lEPSR7U0VSVklDRV9ESVNDT1JEX1RPS0VOfScKICAgICAgLSAnU0xBQ0tfSUQ9JHtTRVJWSUNFX1NMQUNLX0lEfScKICAgICAgLSAnU0xBQ0tfU0VDUkVUPSR7U0VSVklDRV9TTEFDS19TRUNSRVR9JwogICAgICAtICdTTEFDS19TSUdOSU5HX1NFQ1JFVD0ke1NMQUNLX1NJR05JTkdfU0VDUkVUfScKICAgICAgLSAnTUFTVE9ET05fQ0xJRU5UX0lEPSR7U0VSVklDRV9NQVNUT0RPTl9JRH0nCiAgICAgIC0gJ01BU1RPRE9OX0NMSUVOVF9TRUNSRVQ9JHtTRVJWSUNFX01BU1RPRE9OX1NFQ1JFVH0nCiAgICAgIC0gJ0JFRUhJSVZFX0FQSV9LRVk9JHtTRVJWSUNFX0JFRUhJSVZFX0tFWX0nCiAgICAgIC0gJ0JFRUhJSVZFX1BVQkxJQ0FUSU9OX0lEPSR7U0VSVklDRV9CRUVISUlWRV9QVUJJRH0nCiAgICAgIC0gJ09QRU5BSV9BUElfS0VZPSR7U0VSVklDRV9PUEVOQUlfS0VZfScKICAgICAgLSAnTkVYVF9QVUJMSUNfRElTQ09SRF9TVVBQT1JUPSR7TkVYVF9QVUJMSUNfRElTQ09SRF9TVVBQT1JUfScKICAgICAgLSAnTkVYVF9QVUJMSUNfUE9MT1ROTz0ke05FWFRfUFVCTElDX1BPTE9UTk99JwogICAgICAtIElTX0dFTkVSQUw9dHJ1ZQogICAgICAtICdOWF9BRERfUExVR0lOUz0ke05YX0FERF9QTFVHSU5TOi1mYWxzZX0nCiAgICAgIC0gJ0ZFRV9BTU9VTlQ9JHtGRUVfQU1PVU5UOi0wLjA1fScKICAgICAgLSAnU1RSSVBFX1BVQkxJU0hBQkxFX0tFWT0ke1NUUklQRV9QVUJMSVNIQUJMRV9LRVl9JwogICAgICAtICdTVFJJUEVfU0VDUkVUX0tFWT0ke1NUUklQRV9TRUNSRVRfS0VZfScKICAgICAgLSAnU1RSSVBFX1NJR05JTkdfS0VZPSR7U1RSSVBFX1NJR05JTkdfS0VZfScKICAgICAgLSAnU1RSSVBFX1NJR05JTkdfS0VZX0NPTk5FQ1Q9JHtTVFJJUEVfU0lHTklOR19LRVlfQ09OTkVDVH0nCiAgICB2b2x1bWVzOgogICAgICAtICdwb3N0aXpfY29uZmlnOi9jb25maWcvJwogICAgICAtICdwb3N0aXpfdXBsb2FkczovdXBsb2Fkcy8nCiAgICBkZXBlbmRzX29uOgogICAgICBwb3N0Z3JlczoKICAgICAgICBjb25kaXRpb246IHNlcnZpY2VfaGVhbHRoeQogICAgICByZWRpczoKICAgICAgICBjb25kaXRpb246IHNlcnZpY2VfaGVhbHRoeQogICAgaGVhbHRoY2hlY2s6CiAgICAgIHRlc3Q6CiAgICAgICAgLSBDTUQtU0hFTEwKICAgICAgICAtICd3Z2V0IC1xTy0gaHR0cDovLzEyNy4wLjAuMTo1MDAwLycKICAgICAgaW50ZXJ2YWw6IDVzCiAgICAgIHRpbWVvdXQ6IDIwcwogICAgICByZXRyaWVzOiAxMAogIHBvc3RncmVzOgogICAgaW1hZ2U6ICdwb3N0Z3JlczoxNC41JwogICAgdm9sdW1lczoKICAgICAgLSAncG9zdGl6X3Bvc3RncmVzcWxfZGF0YTovdmFyL2xpYi9wb3N0Z3Jlc3FsL2RhdGEnCiAgICBlbnZpcm9ubWVudDoKICAgICAgLSBQT1NUR1JFU19VU0VSPXBvc3RncmVzCiAgICAgIC0gJ1BPU1RHUkVTX1BBU1NXT1JEPSR7U0VSVklDRV9QQVNTV09SRF9QT1NUR1JFU1FMfScKICAgICAgLSAnUE9TVEdSRVNfREI9JHtQT1NUR1JFU1FMX0RBVEFCQVNFOi1wb3N0aXotZGJ9JwogICAgaGVhbHRoY2hlY2s6CiAgICAgIHRlc3Q6CiAgICAgICAgLSBDTUQtU0hFTEwKICAgICAgICAtICdwZ19pc3JlYWR5IC1VICQke1BPU1RHUkVTX1VTRVJ9IC1kICQke1BPU1RHUkVTX0RCOi1wb3N0aXotZGJ9JwogICAgICBpbnRlcnZhbDogNXMKICAgICAgdGltZW91dDogMjBzCiAgICAgIHJldHJpZXM6IDEwCiAgcmVkaXM6CiAgICBpbWFnZTogJ3JlZGlzOjcuMicKICAgIGVudmlyb25tZW50OgogICAgICAtICdSRURJU19QQVNTV09SRD0ke1NFUlZJQ0VfUEFTU1dPUkRfUkVESVN9JwogICAgY29tbWFuZDogJ3JlZGlzLXNlcnZlciAtLXJlcXVpcmVwYXNzICR7U0VSVklDRV9QQVNTV09SRF9SRURJU30nCiAgICB2b2x1bWVzOgogICAgICAtICdwb3N0aXpfcmVkaXNfZGF0YTovZGF0YScKICAgIGhlYWx0aGNoZWNrOgogICAgICB0ZXN0OgogICAgICAgIC0gQ01ECiAgICAgICAgLSByZWRpcy1jbGkKICAgICAgICAtICctYScKICAgICAgICAtICcke1NFUlZJQ0VfUEFTU1dPUkRfUkVESVN9JwogICAgICAgIC0gcGluZwogICAgICBpbnRlcnZhbDogNXMKICAgICAgdGltZW91dDogMTBzCiAgICAgIHJldHJpZXM6IDIwCg==",
+ "compose": "c2VydmljZXM6CiAgcG9zdGl6OgogICAgaW1hZ2U6ICdnaGNyLmlvL2dpdHJvb21ocS9wb3N0aXotYXBwOmxhdGVzdCcKICAgIGVudmlyb25tZW50OgogICAgICAtIFNFUlZJQ0VfRlFETl9QT1NUSVpfNTAwMAogICAgICAtICdNQUlOX1VSTD0ke1NFUlZJQ0VfRlFETl9QT1NUSVp9JwogICAgICAtICdGUk9OVEVORF9VUkw9JHtTRVJWSUNFX0ZRRE5fUE9TVElafScKICAgICAgLSAnTkVYVF9QVUJMSUNfQkFDS0VORF9VUkw9JHtTRVJWSUNFX0ZRRE5fUE9TVElafS9hcGknCiAgICAgIC0gJ0pXVF9TRUNSRVQ9JHtTRVJWSUNFX1BBU1NXT1JEX0pXVFNFQ1JFVH0nCiAgICAgIC0gJ0RBVEFCQVNFX1VSTD1wb3N0Z3Jlc3FsOi8vcG9zdGdyZXM6JHtTRVJWSUNFX1BBU1NXT1JEX1BPU1RHUkVTUUx9QHBvc3RncmVzOjU0MzIvJHtQT1NUR1JFU1FMX0RBVEFCQVNFOi1wb3N0aXotZGJ9JwogICAgICAtICdSRURJU19VUkw9cmVkaXM6Ly9kZWZhdWx0OiR7U0VSVklDRV9QQVNTV09SRF9SRURJU31AcmVkaXM6NjM3OScKICAgICAgLSAnQkFDS0VORF9JTlRFUk5BTF9VUkw9aHR0cDovL2xvY2FsaG9zdDozMDAwJwogICAgICAtICdDTE9VREZMQVJFX0FDQ09VTlRfSUQ9JHtDTE9VREZMQVJFX0FDQ09VTlRfSUR9JwogICAgICAtICdDTE9VREZMQVJFX0FDQ0VTU19LRVk9JHtDTE9VREZMQVJFX0FDQ0VTU19LRVl9JwogICAgICAtICdDTE9VREZMQVJFX1NFQ1JFVF9BQ0NFU1NfS0VZPSR7Q0xPVURGTEFSRV9TRUNSRVRfQUNDRVNTX0tFWX0nCiAgICAgIC0gJ0NMT1VERkxBUkVfQlVDS0VUTkFNRT0ke0NMT1VERkxBUkVfQlVDS0VUTkFNRX0nCiAgICAgIC0gJ0NMT1VERkxBUkVfQlVDS0VUX1VSTD0ke0NMT1VERkxBUkVfQlVDS0VUX1VSTH0nCiAgICAgIC0gJ0NMT1VERkxBUkVfUkVHSU9OPSR7Q0xPVURGTEFSRV9SRUdJT059JwogICAgICAtICdTVE9SQUdFX1BST1ZJREVSPSR7U1RPUkFHRV9QUk9WSURFUjotbG9jYWx9JwogICAgICAtICdVUExPQURfRElSRUNUT1JZPSR7VVBMT0FEX0RJUkVDVE9SWTotL3VwbG9hZHN9JwogICAgICAtICdORVhUX1BVQkxJQ19VUExPQURfRElSRUNUT1JZPSR7TkVYVF9QVUJMSUNfVVBMT0FEX0RJUkVDVE9SWTotL3VwbG9hZHN9JwogICAgICAtICdORVhUX1BVQkxJQ19VUExPQURfU1RBVElDX0RJUkVDVE9SWT0ke05FWFRfUFVCTElDX1VQTE9BRF9TVEFUSUNfRElSRUNUT1JZfScKICAgICAgLSAnUkVTRU5EX0FQSV9LRVk9JHtSRVNFTkRfQVBJX0tFWX0nCiAgICAgIC0gJ0VNQUlMX0ZST01fQUREUkVTUz0ke0VNQUlMX0ZST01fQUREUkVTU30nCiAgICAgIC0gJ0VNQUlMX0ZST01fTkFNRT0ke0VNQUlMX0ZST01fTkFNRX0nCiAgICAgIC0gJ0VNQUlMX1BST1ZJREVSPSR7RU1BSUxfUFJPVklERVJ9JwogICAgICAtICdYX0FQSV9LRVk9JHtTRVJWSUNFX1hfQVBJfScKICAgICAgLSAnWF9BUElfU0VDUkVUPSR7U0VSVklDRV9YX1NFQ1JFVH0nCiAgICAgIC0gJ0xJTktFRElOX0NMSUVOVF9JRD0ke1NFUlZJQ0VfTElOS0VESU5fSUR9JwogICAgICAtICdMSU5LRURJTl9DTElFTlRfU0VDUkVUPSR7U0VSVklDRV9MSU5LRURJTl9TRUNSRVR9JwogICAgICAtICdSRURESVRfQ0xJRU5UX0lEPSR7U0VSVklDRV9SRURESVRfQVBJfScKICAgICAgLSAnUkVERElUX0NMSUVOVF9TRUNSRVQ9JHtTRVJWSUNFX1JFRERJVF9TRUNSRVR9JwogICAgICAtICdHSVRIVUJfQ0xJRU5UX0lEPSR7U0VSVklDRV9HSVRIVUJfSUR9JwogICAgICAtICdHSVRIVUJfQ0xJRU5UX1NFQ1JFVD0ke1NFUlZJQ0VfR0lUSFVCX1NFQ1JFVH0nCiAgICAgIC0gJ1RIUkVBRFNfQVBQX0lEPSR7U0VSVklDRV9USFJFQURTX0lEfScKICAgICAgLSAnVEhSRUFEU19BUFBfU0VDUkVUPSR7U0VSVklDRV9USFJFQURTX1NFQ1JFVH0nCiAgICAgIC0gJ0ZBQ0VCT09LX0FQUF9JRD0ke1NFUlZJQ0VfRkFDRUJPT0tfSUR9JwogICAgICAtICdGQUNFQk9PS19BUFBfU0VDUkVUPSR7U0VSVklDRV9GQUNFQk9PS19TRUNSRVR9JwogICAgICAtICdZT1VUVUJFX0NMSUVOVF9JRD0ke1NFUlZJQ0VfWU9VVFVCRV9JRH0nCiAgICAgIC0gJ1lPVVRVQkVfQ0xJRU5UX1NFQ1JFVD0ke1NFUlZJQ0VfWU9VVFVCRV9TRUNSRVR9JwogICAgICAtICdUSUtUT0tfQ0xJRU5UX0lEPSR7U0VSVklDRV9USUtUT0tfSUR9JwogICAgICAtICdUSUtUT0tfQ0xJRU5UX1NFQ1JFVD0ke1NFUlZJQ0VfVElLVE9LX1NFQ1JFVH0nCiAgICAgIC0gJ1BJTlRFUkVTVF9DTElFTlRfSUQ9JHtTRVJWSUNFX1BJTlRFUkVTVF9JRH0nCiAgICAgIC0gJ1BJTlRFUkVTVF9DTElFTlRfU0VDUkVUPSR7U0VSVklDRV9QSU5URVJFU1RfU0VDUkVUfScKICAgICAgLSAnRFJJQkJCTEVfQ0xJRU5UX0lEPSR7U0VSVklDRV9EUklCQkxFX0lEfScKICAgICAgLSAnRFJJQkJCTEVfQ0xJRU5UX1NFQ1JFVD0ke1NFUlZJQ0VfRFJJQkJMRV9TRUNSRVR9JwogICAgICAtICdESVNDT1JEX0NMSUVOVF9JRD0ke1NFUlZJQ0VfRElTQ09SRF9JRH0nCiAgICAgIC0gJ0RJU0NPUkRfQ0xJRU5UX1NFQ1JFVD0ke1NFUlZJQ0VfRElTQ09SRF9TRUNSRVR9JwogICAgICAtICdESVNDT1JEX0JPVF9UT0tFTl9JRD0ke1NFUlZJQ0VfRElTQ09SRF9UT0tFTn0nCiAgICAgIC0gJ1NMQUNLX0lEPSR7U0VSVklDRV9TTEFDS19JRH0nCiAgICAgIC0gJ1NMQUNLX1NFQ1JFVD0ke1NFUlZJQ0VfU0xBQ0tfU0VDUkVUfScKICAgICAgLSAnU0xBQ0tfU0lHTklOR19TRUNSRVQ9JHtTTEFDS19TSUdOSU5HX1NFQ1JFVH0nCiAgICAgIC0gJ01BU1RPRE9OX0NMSUVOVF9JRD0ke1NFUlZJQ0VfTUFTVE9ET05fSUR9JwogICAgICAtICdNQVNUT0RPTl9DTElFTlRfU0VDUkVUPSR7U0VSVklDRV9NQVNUT0RPTl9TRUNSRVR9JwogICAgICAtICdCRUVISUlWRV9BUElfS0VZPSR7U0VSVklDRV9CRUVISUlWRV9LRVl9JwogICAgICAtICdCRUVISUlWRV9QVUJMSUNBVElPTl9JRD0ke1NFUlZJQ0VfQkVFSElJVkVfUFVCSUR9JwogICAgICAtICdPUEVOQUlfQVBJX0tFWT0ke1NFUlZJQ0VfT1BFTkFJX0tFWX0nCiAgICAgIC0gJ05FWFRfUFVCTElDX0RJU0NPUkRfU1VQUE9SVD0ke05FWFRfUFVCTElDX0RJU0NPUkRfU1VQUE9SVH0nCiAgICAgIC0gJ05FWFRfUFVCTElDX1BPTE9UTk89JHtORVhUX1BVQkxJQ19QT0xPVE5PfScKICAgICAgLSBJU19HRU5FUkFMPXRydWUKICAgICAgLSAnTlhfQUREX1BMVUdJTlM9JHtOWF9BRERfUExVR0lOUzotZmFsc2V9JwogICAgICAtICdGRUVfQU1PVU5UPSR7RkVFX0FNT1VOVDotMC4wNX0nCiAgICAgIC0gJ1NUUklQRV9QVUJMSVNIQUJMRV9LRVk9JHtTVFJJUEVfUFVCTElTSEFCTEVfS0VZfScKICAgICAgLSAnU1RSSVBFX1NFQ1JFVF9LRVk9JHtTVFJJUEVfU0VDUkVUX0tFWX0nCiAgICAgIC0gJ1NUUklQRV9TSUdOSU5HX0tFWT0ke1NUUklQRV9TSUdOSU5HX0tFWX0nCiAgICAgIC0gJ1NUUklQRV9TSUdOSU5HX0tFWV9DT05ORUNUPSR7U1RSSVBFX1NJR05JTkdfS0VZX0NPTk5FQ1R9JwogICAgdm9sdW1lczoKICAgICAgLSAncG9zdGl6X2NvbmZpZzovY29uZmlnLycKICAgICAgLSAncG9zdGl6X3VwbG9hZHM6L3VwbG9hZHMvJwogICAgZGVwZW5kc19vbjoKICAgICAgcG9zdGdyZXM6CiAgICAgICAgY29uZGl0aW9uOiBzZXJ2aWNlX2hlYWx0aHkKICAgICAgcmVkaXM6CiAgICAgICAgY29uZGl0aW9uOiBzZXJ2aWNlX2hlYWx0aHkKICAgIGhlYWx0aGNoZWNrOgogICAgICB0ZXN0OgogICAgICAgIC0gQ01ELVNIRUxMCiAgICAgICAgLSAnd2dldCAtcU8tIGh0dHA6Ly8xMjcuMC4wLjE6NTAwMC8nCiAgICAgIGludGVydmFsOiA1cwogICAgICB0aW1lb3V0OiAyMHMKICAgICAgcmV0cmllczogMTAKICBwb3N0Z3JlczoKICAgIGltYWdlOiAncG9zdGdyZXM6MTQuNScKICAgIHZvbHVtZXM6CiAgICAgIC0gJ3Bvc3Rpel9wb3N0Z3Jlc3FsX2RhdGE6L3Zhci9saWIvcG9zdGdyZXNxbC9kYXRhJwogICAgZW52aXJvbm1lbnQ6CiAgICAgIC0gUE9TVEdSRVNfVVNFUj1wb3N0Z3JlcwogICAgICAtICdQT1NUR1JFU19QQVNTV09SRD0ke1NFUlZJQ0VfUEFTU1dPUkRfUE9TVEdSRVNRTH0nCiAgICAgIC0gJ1BPU1RHUkVTX0RCPSR7UE9TVEdSRVNRTF9EQVRBQkFTRTotcG9zdGl6LWRifScKICAgIGhlYWx0aGNoZWNrOgogICAgICB0ZXN0OgogICAgICAgIC0gQ01ELVNIRUxMCiAgICAgICAgLSAncGdfaXNyZWFkeSAtVSAkJHtQT1NUR1JFU19VU0VSfSAtZCAkJHtQT1NUR1JFU19EQjotcG9zdGl6LWRifScKICAgICAgaW50ZXJ2YWw6IDVzCiAgICAgIHRpbWVvdXQ6IDIwcwogICAgICByZXRyaWVzOiAxMAogIHJlZGlzOgogICAgaW1hZ2U6ICdyZWRpczo3LjInCiAgICBlbnZpcm9ubWVudDoKICAgICAgLSAnUkVESVNfUEFTU1dPUkQ9JHtTRVJWSUNFX1BBU1NXT1JEX1JFRElTfScKICAgIGNvbW1hbmQ6ICdyZWRpcy1zZXJ2ZXIgLS1yZXF1aXJlcGFzcyAke1NFUlZJQ0VfUEFTU1dPUkRfUkVESVN9JwogICAgdm9sdW1lczoKICAgICAgLSAncG9zdGl6X3JlZGlzX2RhdGE6L2RhdGEnCiAgICBoZWFsdGhjaGVjazoKICAgICAgdGVzdDoKICAgICAgICAtIENNRAogICAgICAgIC0gcmVkaXMtY2xpCiAgICAgICAgLSAnLWEnCiAgICAgICAgLSAnJHtTRVJWSUNFX1BBU1NXT1JEX1JFRElTfScKICAgICAgICAtIHBpbmcKICAgICAgaW50ZXJ2YWw6IDVzCiAgICAgIHRpbWVvdXQ6IDEwcwogICAgICByZXRyaWVzOiAyMAo=",
"tags": [
"post everywhere",
"social media",
@@ -2971,7 +2971,7 @@
"privacy",
"search engine"
],
- "logo": "svgs/default.webp",
+ "logo": "svgs/whoogle.png",
"minversion": "0.0.0",
"port": "5000"
},