feat(services): add Executor one-click deployment template (#11530)
This commit is contained in:
parent
29c7b043f3
commit
c2a23466ca
5 changed files with 120 additions and 0 deletions
BIN
public/svgs/executor.png
Normal file
BIN
public/svgs/executor.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 173 KiB |
35
templates/compose/executor.yaml
Normal file
35
templates/compose/executor.yaml
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
# documentation: https://executor.sh/docs/hosted/docker
|
||||||
|
# slogan: Self-hosted AI agent integrations and code execution server.
|
||||||
|
# category: development
|
||||||
|
# tags: executor,ai,agents,mcp,automation,development
|
||||||
|
# logo: svgs/executor.png
|
||||||
|
# port: 4788
|
||||||
|
|
||||||
|
services:
|
||||||
|
executor:
|
||||||
|
image: 'ghcr.io/rhyssullivan/executor-selfhost:${EXECUTOR_VERSION:-latest}'
|
||||||
|
environment:
|
||||||
|
- SERVICE_URL_EXECUTOR_4788
|
||||||
|
- EXECUTOR_WEB_BASE_URL=${SERVICE_URL_EXECUTOR_4788}
|
||||||
|
- EXECUTOR_HOST=${EXECUTOR_HOST:-0.0.0.0}
|
||||||
|
- PORT=${PORT:-4788}
|
||||||
|
- EXECUTOR_DATA_DIR=/data
|
||||||
|
- EXECUTOR_DB_PATH=${EXECUTOR_DB_PATH:-/data/data.db}
|
||||||
|
- EXECUTOR_ORG_NAME=${EXECUTOR_ORG_NAME:-Default}
|
||||||
|
- EXECUTOR_ORG_SLUG=${EXECUTOR_ORG_SLUG:-default}
|
||||||
|
- EXECUTOR_ALLOW_LOCAL_NETWORK=${EXECUTOR_ALLOW_LOCAL_NETWORK:-false}
|
||||||
|
volumes:
|
||||||
|
- executor-data:/data
|
||||||
|
healthcheck:
|
||||||
|
test:
|
||||||
|
- CMD
|
||||||
|
- bun
|
||||||
|
- -e
|
||||||
|
- "fetch(`http://127.0.0.1:${process.env.PORT||4788}/api/health`).then(r=>process.exit(r.ok?0:1),()=>process.exit(1))"
|
||||||
|
interval: 30s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 5
|
||||||
|
start_period: 20s
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
executor-data:
|
||||||
|
|
@ -1400,6 +1400,24 @@
|
||||||
"template_last_updated_at": "2025-08-17T18:23:57+02:00",
|
"template_last_updated_at": "2025-08-17T18:23:57+02:00",
|
||||||
"port": "80"
|
"port": "80"
|
||||||
},
|
},
|
||||||
|
"executor": {
|
||||||
|
"documentation": "https://executor.sh/docs/hosted/docker?utm_source=coolify.io",
|
||||||
|
"slogan": "Self-hosted AI agent integrations and code execution server.",
|
||||||
|
"compose": "c2VydmljZXM6CiAgZXhlY3V0b3I6CiAgICBpbWFnZTogJ2doY3IuaW8vcmh5c3N1bGxpdmFuL2V4ZWN1dG9yLXNlbGZob3N0OiR7RVhFQ1VUT1JfVkVSU0lPTjotbGF0ZXN0fScKICAgIGVudmlyb25tZW50OgogICAgICAtIFNFUlZJQ0VfVVJMX0VYRUNVVE9SXzQ3ODgKICAgICAgLSAnRVhFQ1VUT1JfV0VCX0JBU0VfVVJMPSR7U0VSVklDRV9VUkxfRVhFQ1VUT1JfNDc4OH0nCiAgICAgIC0gJ0VYRUNVVE9SX0hPU1Q9JHtFWEVDVVRPUl9IT1NUOi0wLjAuMC4wfScKICAgICAgLSAnUE9SVD0ke1BPUlQ6LTQ3ODh9JwogICAgICAtIEVYRUNVVE9SX0RBVEFfRElSPS9kYXRhCiAgICAgIC0gJ0VYRUNVVE9SX0RCX1BBVEg9JHtFWEVDVVRPUl9EQl9QQVRIOi0vZGF0YS9kYXRhLmRifScKICAgICAgLSAnRVhFQ1VUT1JfT1JHX05BTUU9JHtFWEVDVVRPUl9PUkdfTkFNRTotRGVmYXVsdH0nCiAgICAgIC0gJ0VYRUNVVE9SX09SR19TTFVHPSR7RVhFQ1VUT1JfT1JHX1NMVUc6LWRlZmF1bHR9JwogICAgICAtICdFWEVDVVRPUl9BTExPV19MT0NBTF9ORVRXT1JLPSR7RVhFQ1VUT1JfQUxMT1dfTE9DQUxfTkVUV09SSzotZmFsc2V9JwogICAgdm9sdW1lczoKICAgICAgLSAnZXhlY3V0b3ItZGF0YTovZGF0YScKICAgIGhlYWx0aGNoZWNrOgogICAgICB0ZXN0OgogICAgICAgIC0gQ01ECiAgICAgICAgLSBidW4KICAgICAgICAtICctZScKICAgICAgICAtICdmZXRjaChgaHR0cDovLzEyNy4wLjAuMToke3Byb2Nlc3MuZW52LlBPUlR8fDQ3ODh9L2FwaS9oZWFsdGhgKS50aGVuKHI9PnByb2Nlc3MuZXhpdChyLm9rPzA6MSksKCk9PnByb2Nlc3MuZXhpdCgxKSknCiAgICAgIGludGVydmFsOiAzMHMKICAgICAgdGltZW91dDogNXMKICAgICAgcmV0cmllczogNQogICAgICBzdGFydF9wZXJpb2Q6IDIwcwp2b2x1bWVzOgogIGV4ZWN1dG9yLWRhdGE6IG51bGwK",
|
||||||
|
"tags": [
|
||||||
|
"executor",
|
||||||
|
"ai",
|
||||||
|
"agents",
|
||||||
|
"mcp",
|
||||||
|
"automation",
|
||||||
|
"development"
|
||||||
|
],
|
||||||
|
"category": "development",
|
||||||
|
"logo": "svgs/executor.png",
|
||||||
|
"minversion": "0.0.0",
|
||||||
|
"template_last_updated_at": null,
|
||||||
|
"port": "4788"
|
||||||
|
},
|
||||||
"faraday": {
|
"faraday": {
|
||||||
"documentation": "https://faradaysec.com/?utm_source=coolify.io",
|
"documentation": "https://faradaysec.com/?utm_source=coolify.io",
|
||||||
"slogan": "Faraday is a powerful, open-source, web-based vulnerability management tool.",
|
"slogan": "Faraday is a powerful, open-source, web-based vulnerability management tool.",
|
||||||
|
|
|
||||||
|
|
@ -1400,6 +1400,24 @@
|
||||||
"template_last_updated_at": "2025-08-17T18:23:57+02:00",
|
"template_last_updated_at": "2025-08-17T18:23:57+02:00",
|
||||||
"port": "80"
|
"port": "80"
|
||||||
},
|
},
|
||||||
|
"executor": {
|
||||||
|
"documentation": "https://executor.sh/docs/hosted/docker?utm_source=coolify.io",
|
||||||
|
"slogan": "Self-hosted AI agent integrations and code execution server.",
|
||||||
|
"compose": "c2VydmljZXM6CiAgZXhlY3V0b3I6CiAgICBpbWFnZTogJ2doY3IuaW8vcmh5c3N1bGxpdmFuL2V4ZWN1dG9yLXNlbGZob3N0OiR7RVhFQ1VUT1JfVkVSU0lPTjotbGF0ZXN0fScKICAgIGVudmlyb25tZW50OgogICAgICAtIFNFUlZJQ0VfRlFETl9FWEVDVVRPUl80Nzg4CiAgICAgIC0gJ0VYRUNVVE9SX1dFQl9CQVNFX1VSTD0ke1NFUlZJQ0VfRlFETl9FWEVDVVRPUl80Nzg4fScKICAgICAgLSAnRVhFQ1VUT1JfSE9TVD0ke0VYRUNVVE9SX0hPU1Q6LTAuMC4wLjB9JwogICAgICAtICdQT1JUPSR7UE9SVDotNDc4OH0nCiAgICAgIC0gRVhFQ1VUT1JfREFUQV9ESVI9L2RhdGEKICAgICAgLSAnRVhFQ1VUT1JfREJfUEFUSD0ke0VYRUNVVE9SX0RCX1BBVEg6LS9kYXRhL2RhdGEuZGJ9JwogICAgICAtICdFWEVDVVRPUl9PUkdfTkFNRT0ke0VYRUNVVE9SX09SR19OQU1FOi1EZWZhdWx0fScKICAgICAgLSAnRVhFQ1VUT1JfT1JHX1NMVUc9JHtFWEVDVVRPUl9PUkdfU0xVRzotZGVmYXVsdH0nCiAgICAgIC0gJ0VYRUNVVE9SX0FMTE9XX0xPQ0FMX05FVFdPUks9JHtFWEVDVVRPUl9BTExPV19MT0NBTF9ORVRXT1JLOi1mYWxzZX0nCiAgICB2b2x1bWVzOgogICAgICAtICdleGVjdXRvci1kYXRhOi9kYXRhJwogICAgaGVhbHRoY2hlY2s6CiAgICAgIHRlc3Q6CiAgICAgICAgLSBDTUQKICAgICAgICAtIGJ1bgogICAgICAgIC0gJy1lJwogICAgICAgIC0gJ2ZldGNoKGBodHRwOi8vMTI3LjAuMC4xOiR7cHJvY2Vzcy5lbnYuUE9SVHx8NDc4OH0vYXBpL2hlYWx0aGApLnRoZW4ocj0+cHJvY2Vzcy5leGl0KHIub2s/MDoxKSwoKT0+cHJvY2Vzcy5leGl0KDEpKScKICAgICAgaW50ZXJ2YWw6IDMwcwogICAgICB0aW1lb3V0OiA1cwogICAgICByZXRyaWVzOiA1CiAgICAgIHN0YXJ0X3BlcmlvZDogMjBzCnZvbHVtZXM6CiAgZXhlY3V0b3ItZGF0YTogbnVsbAo=",
|
||||||
|
"tags": [
|
||||||
|
"executor",
|
||||||
|
"ai",
|
||||||
|
"agents",
|
||||||
|
"mcp",
|
||||||
|
"automation",
|
||||||
|
"development"
|
||||||
|
],
|
||||||
|
"category": "development",
|
||||||
|
"logo": "svgs/executor.png",
|
||||||
|
"minversion": "0.0.0",
|
||||||
|
"template_last_updated_at": null,
|
||||||
|
"port": "4788"
|
||||||
|
},
|
||||||
"faraday": {
|
"faraday": {
|
||||||
"documentation": "https://faradaysec.com/?utm_source=coolify.io",
|
"documentation": "https://faradaysec.com/?utm_source=coolify.io",
|
||||||
"slogan": "Faraday is a powerful, open-source, web-based vulnerability management tool.",
|
"slogan": "Faraday is a powerful, open-source, web-based vulnerability management tool.",
|
||||||
|
|
|
||||||
49
tests/Unit/ExecutorServiceTemplateTest.php
Normal file
49
tests/Unit/ExecutorServiceTemplateTest.php
Normal file
|
|
@ -0,0 +1,49 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
it('includes an Executor one-click service template', function () {
|
||||||
|
$templatePath = __DIR__.'/../../templates/compose/executor.yaml';
|
||||||
|
|
||||||
|
expect($templatePath)->toBeFile();
|
||||||
|
|
||||||
|
$compose = file_get_contents($templatePath);
|
||||||
|
|
||||||
|
expect($compose)
|
||||||
|
->toContain('ghcr.io/rhyssullivan/executor-selfhost:${EXECUTOR_VERSION:-latest}')
|
||||||
|
->toContain('SERVICE_URL_EXECUTOR_4788')
|
||||||
|
->toContain('EXECUTOR_WEB_BASE_URL=${SERVICE_URL_EXECUTOR_4788}')
|
||||||
|
->toContain('executor-data:/data')
|
||||||
|
->toContain('http://127.0.0.1:${process.env.PORT||4788}/api/health');
|
||||||
|
|
||||||
|
foreach (['service-templates.json', 'service-templates-latest.json'] as $templateFile) {
|
||||||
|
$templateCatalogPath = __DIR__."/../../templates/{$templateFile}";
|
||||||
|
$templateCatalog = file_get_contents($templateCatalogPath);
|
||||||
|
|
||||||
|
if ($templateCatalog === false) {
|
||||||
|
throw new RuntimeException("Unable to read service template catalog at {$templateCatalogPath}.");
|
||||||
|
}
|
||||||
|
|
||||||
|
$templates = json_decode(
|
||||||
|
$templateCatalog,
|
||||||
|
associative: true,
|
||||||
|
flags: JSON_THROW_ON_ERROR,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect($templates)->toHaveKey('executor');
|
||||||
|
expect($templates['executor']['port'] ?? null)->toBe('4788');
|
||||||
|
expect($templates['executor']['logo'] ?? null)->toBe('svgs/executor.png');
|
||||||
|
expect($templates['executor']['category'] ?? null)->toBe('development');
|
||||||
|
|
||||||
|
$generatedCompose = base64_decode($templates['executor']['compose'], strict: true);
|
||||||
|
|
||||||
|
expect($generatedCompose)
|
||||||
|
->toContain('ghcr.io/rhyssullivan/executor-selfhost:${EXECUTOR_VERSION:-latest}')
|
||||||
|
->toContain('http://127.0.0.1:${process.env.PORT||4788}/api/health')
|
||||||
|
->toContain($templateFile === 'service-templates.json'
|
||||||
|
? 'EXECUTOR_WEB_BASE_URL=${SERVICE_FQDN_EXECUTOR_4788}'
|
||||||
|
: 'EXECUTOR_WEB_BASE_URL=${SERVICE_URL_EXECUTOR_4788}');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('ships the Executor service icon from the public path used by the service picker', function () {
|
||||||
|
expect(__DIR__.'/../../public/svgs/executor.png')->toBeFile();
|
||||||
|
});
|
||||||
Loading…
Reference in a new issue