Compare commits
33
Commits
95dd642243
..
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d34a42868d | ||
|
|
c255b76e12 | ||
|
|
11a3bf2603 | ||
|
|
cb4740ce92 | ||
|
|
b064f69ddf | ||
|
|
375273575e | ||
|
|
a3aca1d937 | ||
|
|
eacefc0184 | ||
|
|
52c13e58c8 | ||
|
|
5297d202f2 | ||
|
|
96733f7019 | ||
|
|
57341fd621 | ||
|
|
d3ea2ec934 | ||
|
|
1ae28324ee | ||
|
|
6ce0790bee | ||
|
|
956d208b13 | ||
|
|
adacaa226c | ||
|
|
431db692c4 | ||
|
|
03951438dc | ||
|
|
561ad299e8 | ||
|
|
1ddcd026ad | ||
|
|
44044848cf | ||
|
|
26df50b15d | ||
|
|
c508d50d00 | ||
|
|
4b21030d28 | ||
|
|
e2b6a35b26 | ||
|
|
405524b036 | ||
|
|
7a58959869 | ||
|
|
0a5476793e | ||
|
|
389d4e5b13 | ||
|
|
bb8fdc64ba | ||
|
|
349adb2b95 | ||
|
|
cf81405a3f |
No files matched your search
+29
-3
@@ -74,18 +74,44 @@ describe("n8n-sandbox installation secrets", () => {
|
|||||||
expect(apiKey?.type).toBe('password')
|
expect(apiKey?.type).toBe('password')
|
||||||
expect(apiKey?.required).toBe(true)
|
expect(apiKey?.required).toBe(true)
|
||||||
expect(apiKey?.min).toBeGreaterThanOrEqual(48)
|
expect(apiKey?.min).toBeGreaterThanOrEqual(48)
|
||||||
|
expect(config.port).toBeUndefined()
|
||||||
|
expect(config.tipi_version).toBeGreaterThanOrEqual(5)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("n8n-sandbox post-install documentation", () => {
|
||||||
|
test("documents the actual n8n override and optional SearXNG JSON setup", async () => {
|
||||||
|
const description = await getFile('n8n-sandbox', 'metadata/description.md')
|
||||||
|
|
||||||
|
expect(description).toContain('services:\n n8n-2:\n environment:')
|
||||||
|
expect(description).toContain('N8N_SANDBOX_SERVICE_URL=http://sandbox-api:8080')
|
||||||
|
expect(description).toContain("Runtipi ne demande aucun port pour cette app")
|
||||||
|
expect(description).not.toContain('sandbox-api:<PORT')
|
||||||
|
expect(description).toContain('N8N_SANDBOX_SERVICE_API_KEY=<clé choisie lors de l’installation>')
|
||||||
|
expect(description).toContain('/opt/runtipi/app-data/migrated/searxng/data/settings.yml')
|
||||||
|
expect(description).toContain('- json')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe("modern compose files preserve runtime semantics", () => {
|
describe("modern compose files preserve runtime semantics", () => {
|
||||||
test("n8n-sandbox keeps its one-shot certificate service", async () => {
|
test("n8n-sandbox keeps its certificate bootstrap healthy for Runtipi", async () => {
|
||||||
const fileContent = await getFile('n8n-sandbox', 'docker-compose.yml')
|
const fileContent = await getFile('n8n-sandbox', 'docker-compose.yml')
|
||||||
expect(fileContent).not.toBeNull()
|
expect(fileContent).not.toBeNull()
|
||||||
|
|
||||||
const parsed = YAML.parse(fileContent || '')
|
const parsed = YAML.parse(fileContent || '')
|
||||||
|
const certs = parsed.services?.['sandbox-certs']
|
||||||
|
const api = parsed.services?.['sandbox-api']
|
||||||
|
|
||||||
expect(parsed['x-runtipi']?.schema_version).toBe(2)
|
expect(parsed['x-runtipi']?.schema_version).toBe(2)
|
||||||
expect(parsed.services?.['sandbox-certs']?.restart).toBe('no')
|
const certCommand = certs?.command?.join(' ') || ''
|
||||||
expect(parsed.services?.['sandbox-api']?.['x-runtipi']?.is_main).toBe(true)
|
expect(certs?.restart).toBe('unless-stopped')
|
||||||
|
expect(certCommand).toContain('rm -f /tmp/certs-ready')
|
||||||
|
expect(certCommand).toContain('touch /tmp/certs-ready')
|
||||||
|
expect(certCommand).toContain('tail -f /dev/null')
|
||||||
|
expect(certCommand.indexOf('rm -f /tmp/certs-ready')).toBeLessThan(certCommand.indexOf('bootstrap-mtls.sh'))
|
||||||
|
expect(certs?.healthcheck?.test).toContain('test -f /tmp/certs-ready')
|
||||||
|
expect(api?.depends_on?.['sandbox-certs']?.condition).toBe('service_healthy')
|
||||||
|
expect(api?.['x-runtipi']?.is_main).toBe(true)
|
||||||
expect(parsed.services?.['sandbox-runner-1']?.environment?.SANDBOX_RUNNER_HTTP_BASE_URL).toBe('https://sandbox-runner-1:8080')
|
expect(parsed.services?.['sandbox-runner-1']?.environment?.SANDBOX_RUNNER_HTTP_BASE_URL).toBe('https://sandbox-runner-1:8080')
|
||||||
expect(parsed.services?.['sandbox-runner-1']?.healthcheck?.test).toContain('https://localhost:8080/readyz')
|
expect(parsed.services?.['sandbox-runner-1']?.healthcheck?.test).toContain('https://localhost:8080/readyz')
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -0,0 +1,34 @@
|
|||||||
|
{
|
||||||
|
"name": "Docling",
|
||||||
|
"id": "docling",
|
||||||
|
"available": true,
|
||||||
|
"short_desc": "Extraction de documents pour Open WebUI, avec description des images par un modèle vision",
|
||||||
|
"author": "Docling Project (IBM Research)",
|
||||||
|
"port": 5001,
|
||||||
|
"exposable": false,
|
||||||
|
"dynamic_config": true,
|
||||||
|
"version": "1.37.0",
|
||||||
|
"tipi_version": 5,
|
||||||
|
"categories": [
|
||||||
|
"ai",
|
||||||
|
"utilities"
|
||||||
|
],
|
||||||
|
"description": "Docling Serve convertit les PDF et documents bureautiques en texte structuré. Branché comme moteur d'extraction d'Open WebUI, il peut faire lire chaque page par un modèle vision d'Ollama pour que les images et schémas des PDF entrent dans les bases de connaissances.",
|
||||||
|
"source": "https://github.com/docling-project/docling-serve",
|
||||||
|
"website": "https://docling-project.github.io/docling/",
|
||||||
|
"supported_architectures": [
|
||||||
|
"amd64",
|
||||||
|
"arm64"
|
||||||
|
],
|
||||||
|
"form_fields": [
|
||||||
|
{
|
||||||
|
"type": "password",
|
||||||
|
"label": "Clé d'API Docling",
|
||||||
|
"hint": "Clé que Docling exigera (en-tête X-Api-Key). Choisis-la longue (24 caractères minimum) et colle la même dans Open WebUI > Réglages > Documents > Docling > Clé API.",
|
||||||
|
"min": 24,
|
||||||
|
"max": 128,
|
||||||
|
"required": true,
|
||||||
|
"env_variable": "DOCLING_API_KEY"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
{
|
||||||
|
"schemaVersion": 2,
|
||||||
|
"services": [
|
||||||
|
{
|
||||||
|
"name": "docling",
|
||||||
|
"image": "quay.io/docling-project/docling-serve-cpu:v1.37.0",
|
||||||
|
"isMain": true,
|
||||||
|
"internalPort": "5001",
|
||||||
|
"environment": [
|
||||||
|
{
|
||||||
|
"key": "DOCLING_SERVE_ENABLE_REMOTE_SERVICES",
|
||||||
|
"value": "true"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "DOCLING_SERVE_ENABLE_UI",
|
||||||
|
"value": "false"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "DOCLING_SERVE_MAX_SYNC_WAIT",
|
||||||
|
"value": "14400"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "UVICORN_WORKERS",
|
||||||
|
"value": "1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "DOCLING_SERVE_ENG_LOC_NUM_WORKERS",
|
||||||
|
"value": "1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "TZ",
|
||||||
|
"value": "${TZ:-Europe/Paris}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "DOCLING_SERVE_API_KEY",
|
||||||
|
"value": "${DOCLING_API_KEY}"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
# Docling
|
||||||
|
|
||||||
|
Moteur d'extraction de documents pour Open WebUI.
|
||||||
|
|
||||||
|
Dans Open WebUI : Administration > Réglages > Documents, moteur d'extraction **Docling**, URL `http://docling:5001` (ou `http://<ip-du-serveur>:5001`).
|
||||||
|
|
||||||
|
Pour que les images des PDF soient lues, les paramètres Docling d'Open WebUI envoient chaque page à un modèle vision d'Ollama (pipeline `vlm`). `DOCLING_SERVE_ENABLE_REMOTE_SERVICES` est activé pour ça.
|
||||||
|
|
||||||
|
Source : https://github.com/docling-project/docling-serve
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 3.9 KiB |
@@ -7,22 +7,64 @@
|
|||||||
"hostname": "mediamtx",
|
"hostname": "mediamtx",
|
||||||
"isMain": true,
|
"isMain": true,
|
||||||
"internalPort": "8889",
|
"internalPort": "8889",
|
||||||
"environment": {
|
"environment": [
|
||||||
"MTX_PROTOCOLS": "tcp",
|
{
|
||||||
"MTX_LOGLEVEL": "info",
|
"key": "MTX_PROTOCOLS",
|
||||||
"MTX_LOGDESTINATIONS": "stdout",
|
"value": "tcp"
|
||||||
"MTX_RTSPADDRESS": ":8554",
|
},
|
||||||
"MTX_RTMPADDRESS": ":1935",
|
{
|
||||||
"MTX_HLSADDRESS": ":8888",
|
"key": "MTX_LOGLEVEL",
|
||||||
"MTX_WEBRTCADDRESS": ":8889",
|
"value": "info"
|
||||||
"MTX_SRTADDRESS": ":8890",
|
},
|
||||||
"MTX_APIADDRESS": ":9997",
|
{
|
||||||
"MTX_METRICSADDRESS": ":9998",
|
"key": "MTX_LOGDESTINATIONS",
|
||||||
"MTX_AUTHINTERNALUSERS": "${MTX_API_USERNAME:+${MTX_API_USERNAME}:${MTX_API_PASSWORD}}",
|
"value": "stdout"
|
||||||
"MTX_PATHDEFAULTS_RECORD": "${MTX_RECORD_ENABLED:-false}",
|
},
|
||||||
"MTX_PATHDEFAULTS_RECORDPATH": "./recordings/%path/%Y-%m-%d_%H-%M-%S-%f",
|
{
|
||||||
"MTX_PATHDEFAULTS_RECORDFORMAT": "fmp4"
|
"key": "MTX_RTSPADDRESS",
|
||||||
},
|
"value": ":8554"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "MTX_RTMPADDRESS",
|
||||||
|
"value": ":1935"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "MTX_HLSADDRESS",
|
||||||
|
"value": ":8888"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "MTX_WEBRTCADDRESS",
|
||||||
|
"value": ":8889"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "MTX_SRTADDRESS",
|
||||||
|
"value": ":8890"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "MTX_APIADDRESS",
|
||||||
|
"value": ":9997"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "MTX_METRICSADDRESS",
|
||||||
|
"value": ":9998"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "MTX_AUTHINTERNALUSERS",
|
||||||
|
"value": "${MTX_API_USERNAME:+${MTX_API_USERNAME}:${MTX_API_PASSWORD}}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "MTX_PATHDEFAULTS_RECORD",
|
||||||
|
"value": "${MTX_RECORD_ENABLED:-false}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "MTX_PATHDEFAULTS_RECORDPATH",
|
||||||
|
"value": "./recordings/%path/%Y-%m-%d_%H-%M-%S-%f"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "MTX_PATHDEFAULTS_RECORDFORMAT",
|
||||||
|
"value": "fmp4"
|
||||||
|
}
|
||||||
|
],
|
||||||
"addPorts": [
|
"addPorts": [
|
||||||
{
|
{
|
||||||
"containerPort": 8554,
|
"containerPort": 8554,
|
||||||
|
|||||||
@@ -5,8 +5,7 @@
|
|||||||
"exposable": false,
|
"exposable": false,
|
||||||
"no_gui": true,
|
"no_gui": true,
|
||||||
"dynamic_config": true,
|
"dynamic_config": true,
|
||||||
"port": 8080,
|
"tipi_version": 5,
|
||||||
"tipi_version": 1,
|
|
||||||
"min_tipi_version": "4.7.0",
|
"min_tipi_version": "4.7.0",
|
||||||
"version": "1.3.0",
|
"version": "1.3.0",
|
||||||
"author": "n8n",
|
"author": "n8n",
|
||||||
|
|||||||
@@ -32,24 +32,32 @@
|
|||||||
services:
|
services:
|
||||||
sandbox-certs:
|
sandbox-certs:
|
||||||
image: n8nio/n8n-sandbox-service-api:1.3.0
|
image: n8nio/n8n-sandbox-service-api:1.3.0
|
||||||
# Obligatoire sous Runtipi : sans cette ligne le builder injecte
|
# Runtipi considere l'app arretee si un seul de ses conteneurs est sorti.
|
||||||
# restart: unless-stopped et ce job one-shot boucle en redemarrage.
|
# Le bootstrap reste donc actif et sain apres la generation idempotente.
|
||||||
restart: "no"
|
restart: unless-stopped
|
||||||
user: "0:0"
|
user: "0:0"
|
||||||
entrypoint: ["sh", "-c"]
|
entrypoint: ["sh", "-c"]
|
||||||
# Genere les certs (idempotent) puis fixe les droits pour l'utilisateur
|
# Genere les certs, fixe les droits pour sandbox-api, publie l'etat ready,
|
||||||
# sandbox-api de l'image : /tls/api et le repertoire SQLite de l'API
|
# puis reste actif sans ouvrir de port ni lancer de service reseau.
|
||||||
# (en bind mount, Docker cree le dossier en root sinon).
|
|
||||||
command:
|
command:
|
||||||
- >
|
- >
|
||||||
|
rm -f /tmp/certs-ready &&
|
||||||
bootstrap-mtls.sh --out-dir /tls --api-san sandbox-api
|
bootstrap-mtls.sh --out-dir /tls --api-san sandbox-api
|
||||||
--control-san-prefix sandbox-runner &&
|
--control-san-prefix sandbox-runner &&
|
||||||
chown -R sandbox-api:sandbox-api /tls/api /var/lib/n8n-sandbox-api
|
chown -R sandbox-api:sandbox-api /tls/api /var/lib/n8n-sandbox-api &&
|
||||||
|
touch /tmp/certs-ready &&
|
||||||
|
exec tail -f /dev/null
|
||||||
environment:
|
environment:
|
||||||
NUM_RUNNERS: "1"
|
NUM_RUNNERS: "1"
|
||||||
volumes:
|
volumes:
|
||||||
- ${APP_DATA_DIR}/data/tls:/tls
|
- ${APP_DATA_DIR}/data/tls:/tls
|
||||||
- ${APP_DATA_DIR}/data/api:/var/lib/n8n-sandbox-api
|
- ${APP_DATA_DIR}/data/api:/var/lib/n8n-sandbox-api
|
||||||
|
healthcheck:
|
||||||
|
test: "test -f /tmp/certs-ready"
|
||||||
|
interval: 5s
|
||||||
|
timeout: 2s
|
||||||
|
retries: 12
|
||||||
|
start_period: 5s
|
||||||
|
|
||||||
sandbox-api:
|
sandbox-api:
|
||||||
image: n8nio/n8n-sandbox-service-api:1.3.0
|
image: n8nio/n8n-sandbox-service-api:1.3.0
|
||||||
@@ -57,7 +65,7 @@ services:
|
|||||||
|
|
||||||
depends_on:
|
depends_on:
|
||||||
sandbox-certs:
|
sandbox-certs:
|
||||||
condition: service_completed_successfully
|
condition: service_healthy
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
SANDBOX_API_KEYS: "${SANDBOX_API_KEYS}"
|
SANDBOX_API_KEYS: "${SANDBOX_API_KEYS}"
|
||||||
|
|||||||
@@ -1,33 +1,79 @@
|
|||||||
# n8n Sandbox Service
|
# n8n Sandbox Service
|
||||||
|
|
||||||
Sandbox auto-hébergé pour l'**AI Assistant** de n8n (setup « Self-host the sandbox manually » de la doc n8n). L'app déploie les trois services de la stack officielle :
|
Sandbox auto-hébergé pour l'**AI Assistant** de n8n (configuration « Self-host the sandbox manually » de la documentation n8n). L'app déploie les trois services de la stack officielle :
|
||||||
|
|
||||||
| Service | Rôle |
|
| Service | Rôle |
|
||||||
|---|---|
|
|---|---|
|
||||||
| `sandbox-certs` | Job one-shot : génère la CA privée et les certificats mTLS, puis s'arrête. |
|
| `sandbox-certs` | Initialise la CA privée et les certificats mTLS, puis reste inactif et sain pour que Runtipi conserve l'app au statut « Démarré ». |
|
||||||
| `sandbox-api` | Point d'entrée HTTP (`:8080`) que n8n appelle pour exécuter du code. |
|
| `sandbox-api` | Point d'entrée HTTP interne (`:8080`) que n8n appelle pour exécuter du code. |
|
||||||
| `sandbox-runner-1` | Docker-in-Docker **privileged** : crée et exécute les conteneurs sandbox. |
|
| `sandbox-runner-1` | Docker-in-Docker **privileged** : crée et exécute les conteneurs sandbox. |
|
||||||
|
|
||||||
## Après l'installation
|
## Après l'installation
|
||||||
|
|
||||||
Lors de l'installation, choisir une clé forte dans le champ **Clé API partagée avec n8n**. Dans l'app officielle **n8n** (paramètres ou `app.env`), ajouter le bloc suivant en recopiant cette même clé :
|
Pendant l'installation, choisir une clé forte dans le champ **Clé API partagée avec n8n** et la conserver dans un gestionnaire de mots de passe.
|
||||||
|
|
||||||
```
|
Dans l'application officielle **n8n**, activer la **configuration utilisateur Docker Compose**, puis ajouter :
|
||||||
N8N_ENABLED_MODULES=instance-ai
|
|
||||||
N8N_INSTANCE_AI_SANDBOX_ENABLED=true
|
```yaml
|
||||||
N8N_INSTANCE_AI_SANDBOX_PROVIDER=n8n-sandbox
|
# Add your docker-compose overrides here.
|
||||||
N8N_INSTANCE_AI_SANDBOX_IMAGE=n8nio/n8n-sandbox-service-sandbox:1.3.0
|
# The overrides will be merged with the generated docker-compose.yml file.
|
||||||
N8N_SANDBOX_SERVICE_URL=http://sandbox-api:8080
|
|
||||||
N8N_SANDBOX_SERVICE_API_KEY=<même valeur que « Clé API partagée avec n8n »>
|
# Heure de Paris
|
||||||
N8N_PROXY_HOPS=1
|
services:
|
||||||
|
n8n-2:
|
||||||
|
environment:
|
||||||
|
- GENERIC_TIMEZONE=Europe/Paris
|
||||||
|
|
||||||
|
# AI Assistant et Sandbox externe
|
||||||
|
- N8N_ENABLED_MODULES=instance-ai
|
||||||
|
- N8N_INSTANCE_AI_SANDBOX_ENABLED=true
|
||||||
|
- N8N_INSTANCE_AI_SANDBOX_PROVIDER=n8n-sandbox
|
||||||
|
- N8N_INSTANCE_AI_SANDBOX_IMAGE=n8nio/n8n-sandbox-service-sandbox:1.3.0
|
||||||
|
- N8N_SANDBOX_SERVICE_URL=http://sandbox-api:8080
|
||||||
|
- N8N_SANDBOX_SERVICE_API_KEY=<clé choisie lors de l’installation>
|
||||||
```
|
```
|
||||||
|
|
||||||
Puis redémarrer n8n et vérifier depuis son conteneur :
|
Remplacer entièrement `<clé choisie lors de l’installation>` par la vraie clé, sans conserver les caractères `<` et `>`. Ne jamais publier cette valeur.
|
||||||
|
|
||||||
|
Le port de `N8N_SANDBOX_SERVICE_URL` reste `8080` : il s'agit du port interne du service Docker. Runtipi ne demande aucun port pour cette app, car elle n'en publie aucun sur l'hôte.
|
||||||
|
|
||||||
|
Enregistrer la configuration, puis redémarrer l'application **n8n**. Pour vérifier la communication depuis son conteneur :
|
||||||
|
|
||||||
|
```sh
|
||||||
|
wget -qO- http://sandbox-api:8080/healthz
|
||||||
```
|
```
|
||||||
wget -qO- http://sandbox-api:8080/healthz # {"status":"ok"}
|
|
||||||
|
La réponse attendue est `{"status":"ok"}`.
|
||||||
|
|
||||||
|
## Recherche web avec SearXNG (facultatif)
|
||||||
|
|
||||||
|
SearXNG est une application séparée et n'est pas nécessaire au fonctionnement du sandbox. L'installer seulement si les workflows ou outils IA de n8n doivent effectuer des recherches web.
|
||||||
|
|
||||||
|
Pour autoriser les réponses JSON de SearXNG, modifier :
|
||||||
|
|
||||||
|
```sh
|
||||||
|
sudo nano /opt/runtipi/app-data/migrated/searxng/data/settings.yml
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Conserver les autres réglages existants et vérifier que le fichier contient :
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
use_default_settings: true
|
||||||
|
|
||||||
|
search:
|
||||||
|
formats:
|
||||||
|
- html
|
||||||
|
- json
|
||||||
|
```
|
||||||
|
|
||||||
|
Contrôle facultatif du contenu et des fins de ligne :
|
||||||
|
|
||||||
|
```sh
|
||||||
|
sudo cat -A /opt/runtipi/app-data/migrated/searxng/data/settings.yml
|
||||||
|
```
|
||||||
|
|
||||||
|
Redémarrer ensuite l'application **SearXNG**, puis redémarrer **n8n** si sa configuration a également été modifiée.
|
||||||
|
|
||||||
## Données persistantes
|
## Données persistantes
|
||||||
|
|
||||||
Tout est sous `app-data/<store>/n8n-sandbox/data/` :
|
Tout est sous `app-data/<store>/n8n-sandbox/data/` :
|
||||||
|
|||||||
@@ -29,10 +29,16 @@
|
|||||||
"readOnly": true
|
"readOnly": true
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"environment": {
|
"environment": [
|
||||||
"NGINX_HOST": "${NGINX_SERVER_NAME:-localhost}",
|
{
|
||||||
"TZ": "${TZ:-Europe/Paris}"
|
"key": "NGINX_HOST",
|
||||||
},
|
"value": "${NGINX_SERVER_NAME:-localhost}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "TZ",
|
||||||
|
"value": "${TZ:-Europe/Paris}"
|
||||||
|
}
|
||||||
|
],
|
||||||
"healthCheck": {
|
"healthCheck": {
|
||||||
"test": "curl --fail http://localhost:80 || exit 1",
|
"test": "curl --fail http://localhost:80 || exit 1",
|
||||||
"interval": "30s",
|
"interval": "30s",
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"name": "RustDesk Server",
|
||||||
|
"id": "rustdesk-server",
|
||||||
|
"available": true,
|
||||||
|
"exposable": false,
|
||||||
|
"no_gui": true,
|
||||||
|
"dynamic_config": true,
|
||||||
|
"tipi_version": 1,
|
||||||
|
"version": "1.1.16",
|
||||||
|
"categories": ["network", "utilities"],
|
||||||
|
"short_desc": "Serveur RustDesk auto-hébergé : annuaire d'ID (hbbs) et relais (hbbr).",
|
||||||
|
"description": "Serveur open source pour RustDesk, l'alternative auto-hébergée à TeamViewer/AnyDesk. hbbs gère l'annuaire d'ID et la mise en relation, hbbr relaie les sessions quand une connexion directe est impossible. Réseau en mode host, comme recommandé par RustDesk.",
|
||||||
|
"author": "RustDesk",
|
||||||
|
"source": "https://github.com/rustdesk/rustdesk-server",
|
||||||
|
"website": "https://rustdesk.com",
|
||||||
|
"form_fields": [],
|
||||||
|
"supported_architectures": ["amd64", "arm64"],
|
||||||
|
"min_tipi_version": "4.5.0"
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
{
|
||||||
|
"schemaVersion": 2,
|
||||||
|
"services": [
|
||||||
|
{
|
||||||
|
"name": "hbbs",
|
||||||
|
"image": "rustdesk/rustdesk-server:1.1.16",
|
||||||
|
"isMain": true,
|
||||||
|
"networkMode": "host",
|
||||||
|
"command": "hbbs",
|
||||||
|
"volumes": [
|
||||||
|
{ "hostPath": "${APP_DATA_DIR}/data", "containerPath": "/root" }
|
||||||
|
],
|
||||||
|
"dependsOn": ["hbbr"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "hbbr",
|
||||||
|
"image": "rustdesk/rustdesk-server:1.1.16",
|
||||||
|
"networkMode": "host",
|
||||||
|
"command": "hbbr",
|
||||||
|
"volumes": [
|
||||||
|
{ "hostPath": "${APP_DATA_DIR}/data", "containerPath": "/root" }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
# RustDesk Server
|
||||||
|
|
||||||
|
Serveur open source pour [RustDesk](https://rustdesk.com), l'outil de prise en main à distance auto-hébergé.
|
||||||
|
|
||||||
|
- **hbbs** : annuaire d'ID, mise en relation des postes (NAT traversal).
|
||||||
|
- **hbbr** : relais des sessions quand une connexion directe est impossible.
|
||||||
|
|
||||||
|
## Réseau
|
||||||
|
|
||||||
|
Les deux services tournent en réseau `host` (recommandation officielle RustDesk). Ports utilisés sur l'hôte :
|
||||||
|
|
||||||
|
| Port | Protocole | Service | Rôle |
|
||||||
|
|-------|-----------|---------|----------------------------------------|
|
||||||
|
| 21115 | TCP | hbbs | Test du type de NAT |
|
||||||
|
| 21116 | TCP + UDP | hbbs | Enregistrement des ID, mise en relation |
|
||||||
|
| 21117 | TCP | hbbr | Relais |
|
||||||
|
| 21118 | TCP | hbbs | Client web |
|
||||||
|
| 21119 | TCP | hbbr | Client web (relais) |
|
||||||
|
|
||||||
|
Ces ports ne passent pas par Traefik : redirigez-les directement (NAT) vers l'hôte Runtipi.
|
||||||
|
> À l'installation, l'option **« Port ouvert »** n'a aucun effet (pas d'interface web à publier) : laissez-la décochée.
|
||||||
|
|
||||||
|
## Données
|
||||||
|
|
||||||
|
`${APP_DATA_DIR}/data` contient la paire de clés du serveur (`id_ed25519`, `id_ed25519.pub`) et la base `db_v2.sqlite3`.
|
||||||
|
**Conservez ces fichiers** : les clients sont configurés avec la clé publique ; la perdre oblige à reconfigurer tous les postes.
|
||||||
|
|
||||||
|
## Configuration des clients
|
||||||
|
|
||||||
|
- Serveur ID : nom de domaine du serveur
|
||||||
|
- Clé : contenu de `id_ed25519.pub`
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 21 KiB |
@@ -9,9 +9,12 @@
|
|||||||
"sh",
|
"sh",
|
||||||
"/scripts/init-certs.sh"
|
"/scripts/init-certs.sh"
|
||||||
],
|
],
|
||||||
"environment": {
|
"environment": [
|
||||||
"CERT_TOOL_VERSION": "4.14"
|
{
|
||||||
},
|
"key": "CERT_TOOL_VERSION",
|
||||||
|
"value": "4.14"
|
||||||
|
}
|
||||||
|
],
|
||||||
"volumes": [
|
"volumes": [
|
||||||
{
|
{
|
||||||
"hostPath": "${APP_DATA_DIR}/data/config",
|
"hostPath": "${APP_DATA_DIR}/data/config",
|
||||||
@@ -71,18 +74,48 @@
|
|||||||
"condition": "service_healthy"
|
"condition": "service_healthy"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"environment": {
|
"environment": [
|
||||||
"OPENSEARCH_JAVA_OPTS": "-Xms1g -Xmx1g -Dlog4j2.formatMsgNoLookups=true",
|
{
|
||||||
"DISABLE_INSTALL_DEMO_CONFIG": "true",
|
"key": "OPENSEARCH_JAVA_OPTS",
|
||||||
"bootstrap.memory_lock": "true",
|
"value": "-Xms1g -Xmx1g -Dlog4j2.formatMsgNoLookups=true"
|
||||||
"network.host": "wazuh.indexer",
|
},
|
||||||
"node.name": "wazuh.indexer",
|
{
|
||||||
"cluster.initial_cluster_manager_nodes": "wazuh.indexer",
|
"key": "DISABLE_INSTALL_DEMO_CONFIG",
|
||||||
"node.max_local_storage_nodes": "1",
|
"value": "true"
|
||||||
"plugins.security.allow_default_init_securityindex": "true",
|
},
|
||||||
"NODES_DN": "CN=wazuh.indexer,OU=Wazuh,O=Wazuh,L=California,C=US",
|
{
|
||||||
"plugins.security.ssl.http.clientauth_mode": "OPTIONAL"
|
"key": "bootstrap.memory_lock",
|
||||||
},
|
"value": "true"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "network.host",
|
||||||
|
"value": "wazuh.indexer"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "node.name",
|
||||||
|
"value": "wazuh.indexer"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "cluster.initial_cluster_manager_nodes",
|
||||||
|
"value": "wazuh.indexer"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "node.max_local_storage_nodes",
|
||||||
|
"value": "1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "plugins.security.allow_default_init_securityindex",
|
||||||
|
"value": "true"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "NODES_DN",
|
||||||
|
"value": "CN=wazuh.indexer,OU=Wazuh,O=Wazuh,L=California,C=US"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "plugins.security.ssl.http.clientauth_mode",
|
||||||
|
"value": "OPTIONAL"
|
||||||
|
}
|
||||||
|
],
|
||||||
"ulimits": {
|
"ulimits": {
|
||||||
"memlock": {
|
"memlock": {
|
||||||
"soft": -1,
|
"soft": -1,
|
||||||
@@ -176,22 +209,64 @@
|
|||||||
"condition": "service_healthy"
|
"condition": "service_healthy"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"environment": {
|
"environment": [
|
||||||
"WAZUH_INDEXER_HOSTS": "wazuh.indexer:9200",
|
{
|
||||||
"WAZUH_NODE_NAME": "manager",
|
"key": "WAZUH_INDEXER_HOSTS",
|
||||||
"WAZUH_NODE_TYPE": "master",
|
"value": "wazuh.indexer:9200"
|
||||||
"WAZUH_CLUSTER_NODES": "wazuh.manager",
|
},
|
||||||
"WAZUH_CLUSTER_BIND_ADDR": "wazuh.manager",
|
{
|
||||||
"INDEXER_URL": "https://wazuh.indexer:9200",
|
"key": "WAZUH_NODE_NAME",
|
||||||
"INDEXER_USERNAME": "${INDEXER_USERNAME:-admin}",
|
"value": "manager"
|
||||||
"INDEXER_PASSWORD": "${INDEXER_PASSWORD:-admin}",
|
},
|
||||||
"FILEBEAT_SSL_VERIFICATION_MODE": "full",
|
{
|
||||||
"SSL_CERTIFICATE_AUTHORITIES": "/var/ossec/etc/certs/root-ca.pem",
|
"key": "WAZUH_NODE_TYPE",
|
||||||
"SSL_CERTIFICATE": "/var/ossec/etc/certs/server.pem",
|
"value": "master"
|
||||||
"SSL_KEY": "/var/ossec/etc/certs/server-key.pem",
|
},
|
||||||
"API_USERNAME": "wazuh-wui",
|
{
|
||||||
"API_PASSWORD": "${API_PASSWORD:-MyS3cr37P450r.*-}"
|
"key": "WAZUH_CLUSTER_NODES",
|
||||||
},
|
"value": "wazuh.manager"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "WAZUH_CLUSTER_BIND_ADDR",
|
||||||
|
"value": "wazuh.manager"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "INDEXER_URL",
|
||||||
|
"value": "https://wazuh.indexer:9200"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "INDEXER_USERNAME",
|
||||||
|
"value": "${INDEXER_USERNAME:-admin}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "INDEXER_PASSWORD",
|
||||||
|
"value": "${INDEXER_PASSWORD:-admin}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "FILEBEAT_SSL_VERIFICATION_MODE",
|
||||||
|
"value": "full"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "SSL_CERTIFICATE_AUTHORITIES",
|
||||||
|
"value": "/var/ossec/etc/certs/root-ca.pem"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "SSL_CERTIFICATE",
|
||||||
|
"value": "/var/ossec/etc/certs/server.pem"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "SSL_KEY",
|
||||||
|
"value": "/var/ossec/etc/certs/server-key.pem"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "API_USERNAME",
|
||||||
|
"value": "wazuh-wui"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "API_PASSWORD",
|
||||||
|
"value": "${API_PASSWORD:-MyS3cr37P450r.*-}"
|
||||||
|
}
|
||||||
|
],
|
||||||
"ulimits": {
|
"ulimits": {
|
||||||
"memlock": {
|
"memlock": {
|
||||||
"soft": -1,
|
"soft": -1,
|
||||||
@@ -293,21 +368,60 @@
|
|||||||
"condition": "service_healthy"
|
"condition": "service_healthy"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"environment": {
|
"environment": [
|
||||||
"SERVER_HOST": "0.0.0.0",
|
{
|
||||||
"OPENSEARCH_HOSTS": "https://wazuh.indexer:9200",
|
"key": "SERVER_HOST",
|
||||||
"SERVER_SSL_ENABLED": "true",
|
"value": "0.0.0.0"
|
||||||
"INDEXER_USERNAME": "${INDEXER_USERNAME:-admin}",
|
},
|
||||||
"INDEXER_PASSWORD": "${INDEXER_PASSWORD:-admin}",
|
{
|
||||||
"WAZUH_API_URL": "https://wazuh.manager",
|
"key": "OPENSEARCH_HOSTS",
|
||||||
"DASHBOARD_USERNAME": "${DASHBOARD_USERNAME:-kibanaserver}",
|
"value": "https://wazuh.indexer:9200"
|
||||||
"DASHBOARD_PASSWORD": "${DASHBOARD_PASSWORD:-kibanaserver}",
|
},
|
||||||
"API_USERNAME": "wazuh-wui",
|
{
|
||||||
"API_PASSWORD": "${API_PASSWORD:-MyS3cr37P450r.*-}",
|
"key": "SERVER_SSL_ENABLED",
|
||||||
"SERVER_SSL_CERTIFICATE": "/usr/share/wazuh-dashboard/config/certs/dashboard.pem",
|
"value": "true"
|
||||||
"SERVER_SSL_KEY": "/usr/share/wazuh-dashboard/config/certs/dashboard-key.pem",
|
},
|
||||||
"OPENSEARCH_SSL_CERTIFICATE_AUTHORITIES": "/usr/share/wazuh-dashboard/config/certs/root-ca.pem"
|
{
|
||||||
},
|
"key": "INDEXER_USERNAME",
|
||||||
|
"value": "${INDEXER_USERNAME:-admin}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "INDEXER_PASSWORD",
|
||||||
|
"value": "${INDEXER_PASSWORD:-admin}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "WAZUH_API_URL",
|
||||||
|
"value": "https://wazuh.manager"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "DASHBOARD_USERNAME",
|
||||||
|
"value": "${DASHBOARD_USERNAME:-kibanaserver}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "DASHBOARD_PASSWORD",
|
||||||
|
"value": "${DASHBOARD_PASSWORD:-kibanaserver}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "API_USERNAME",
|
||||||
|
"value": "wazuh-wui"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "API_PASSWORD",
|
||||||
|
"value": "${API_PASSWORD:-MyS3cr37P450r.*-}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "SERVER_SSL_CERTIFICATE",
|
||||||
|
"value": "/usr/share/wazuh-dashboard/config/certs/dashboard.pem"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "SERVER_SSL_KEY",
|
||||||
|
"value": "/usr/share/wazuh-dashboard/config/certs/dashboard-key.pem"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "OPENSEARCH_SSL_CERTIFICATE_AUTHORITIES",
|
||||||
|
"value": "/usr/share/wazuh-dashboard/config/certs/root-ca.pem"
|
||||||
|
}
|
||||||
|
],
|
||||||
"volumes": [
|
"volumes": [
|
||||||
{
|
{
|
||||||
"hostPath": "${APP_DATA_DIR}/data/config/wazuh_ssl_certs",
|
"hostPath": "${APP_DATA_DIR}/data/config/wazuh_ssl_certs",
|
||||||
|
|||||||
Reference in new issue
Block a user