Skip to content

Architecture

┌──────────────┐
Browser ────────┤ Traefik │ TLS termination + Host-rule routing
└──┬───────┬───┘
│ │
┌─────────────▼───┐ ┌─▼──────────────┐ ┌──────────┐
│ pipebase- │ │ pipebase- │ │pipebase- │
│ designer │ │ runtime │ │docs │
│ (Hono on :3000) │ │ (Camel on :8080)│ │(nginx) │
└─────┬───────────┘ └─┬──────────────┘ └──────────┘
│ token-auth │ Camel routes
│ /_api/* │
▼ ▼
┌─────────────────────────┐
│ Internal Docker │
│ network: coolify │
│ │
│ ┌──────────┐ ┌────────┐│ Opt-in (--profile mesh):
│ │ kafka │ │ pulsar ││ cross-runtime message bus
│ └──────────┘ └────────┘│
└─────────────────────────┘
Volumes:
ipaas_ipaas-runtime-routes ← Camel YAML files
ipaas_ipaas-designer-flows ← flow definitions, layouts, params
pipebase-{kafka,pulsar}-data ← broker logs (only with profiles)
  1. Designer (Hono backend + React SPA) — owns the YAML on disk, talks to the runtime over /_api/* to deploy/test/undeploy. Stateless — all persistent state lives in the volume.
  2. Runtime (Camel) — owns the running routes, exposes platform-http: for user-defined HTTP triggers. Hot-reloads via PUT /_api/flows/:id.
  3. Mesh (Kafka + Pulsar) — opt-in. Lets flows on different runtimes communicate via topics rather than direct HTTP.
  1. Author in https://designer.<root> — visual edit on canvas
  2. Save — designer writes flow.camel.yaml + flow.layout.json to its disk volume (ipaas_ipaas-designer-flows)
  3. Deploy — designer reads the YAML, applies parameter substitution (global → per-runtime → per-flow overrides), and PUTs to the runtime’s /_api/flows/:id
  4. Runtime validates the YAML with an ephemeral DefaultCamelContext, stops + removes any existing routes for that flow id, and addRoutes to the live context
  5. Traffic — incoming HTTP at runtime.<root>/<route-path> hits the new route immediately
  1. Client POSTs to https://runtime.<root>/api/<route-id>
  2. Traefik terminates TLS, routes to pipebase-runtime
  3. Camel platform-http dispatches to the matching route
  4. Steps execute — each step’s elapsed time is captured by Camel’s MessageHistory for the run-history feature
  5. Response — the last step’s body is the response body
  6. Run-history notifier persists the exchange to the in-memory ring buffer; the designer’s RunPanel polls /_api/runs?routeId=<id> to render it

Three reasons:

  1. Camel speaks YAML. Translating BPMN→YAML→Camel happens at designer save time; runtime never sees BPMN.
  2. Diffable. Git diffs on Camel YAML are readable; BPMN XML is not.
  3. No bidirectional drift. Edits via the designer round-trip through the translator’s parser/serializer; we test serialize(parse(yaml)) === yaml to guarantee stability.

The BpmnLayout (shapes/edges/extras) is the SPA’s concern, persisted next to the YAML by the designer backend. The runtime treats layout data as opaque — it never reads flow.layout.json.

DataLocationSurvives container rebuild?
Flow YAML (canonical)ipaas_ipaas-runtime-routes volume
Flow definitions + layoutsipaas_ipaas-designer-flows volume
Run historyruntime in-memory ring buffer
Live trace + logsruntime SSE stream
TLS certsTraefik’s acme.json✓ (Traefik volume)
.envrepo / orchestratordepends on backup