Docker Runner
The Succession Runner is a Docker image that executes your pipeline graphs on any machine with Docker — a build server, a NAS, a render farm node, a cloud VM, or a CI pipeline. You design graphs in the desktop app as usual, then run them headless wherever you need them.
Requires a Business plan or higher.
What You Need
- Docker installed on the machine that will run the graph (Docker Desktop on Windows/macOS, Docker Engine on Linux)
- A License Token created in the desktop app (see below)
- A graph file (
.json) exported from your project
Getting the Image
Download succession-runner.tar.gz from the releases page — it is listed as a release asset alongside the desktop installers. Load it into Docker once:
docker load < succession-runner.tar.gz
After loading, docker images lists it as succession-runner.
License Tokens
The runner does not use your account login. Instead it authenticates with a License Token — a scoped credential that can only validate your license, nothing else. If a token ever leaks, you revoke that one token and your account, your login, and your other tokens stay untouched.
To create one:
- Open the desktop app and go to Licensing (avatar menu)
- In the License Tokens section, enter a name (for example
render-server) and pick a lifetime - Click generate. The token (starting with
lt_) is shown once — copy it now and store it somewhere safe, for example your CI secret store
You can see every token’s creation date, expiry, and last use in the same section, and revoke any of them at any time. A revoked token is refused for new container starts and graph deployments within a few minutes. A container already running in sidecar mode will continue until it is restarted — the service does not re-check the token at runtime.
Use one token per machine or pipeline. If a server is decommissioned or a token leaks, you can revoke exactly that one.
Running a Graph
Sidecar Mode (recommended)
The container runs indefinitely: your graph stays deployed and its triggers keep firing — file watchers watch, cron schedules fire, webhooks listen. This is the right mode for anything long-running.
docker run -d --name my-pipeline \
-v /path/to/project:/workspace \
-e SUCCESSION_LICENSE_TOKEN=lt_... \
-e SUCCESSION_GRAPH=my-graph.json \
-e SUCCESSION_TIMEOUT=0 \
succession-runner
Stop it like any container:
docker stop my-pipeline
The graph is stopped cleanly before the container exits.
One-Shot Mode
Without SUCCESSION_TIMEOUT=0, the container deploys the graph and then polls the service health endpoint until two consecutive polls show no active workflows, or until SUCCESSION_TIMEOUT seconds elapse.
What this does and does not guarantee. Exit code 0 means the graph deployed successfully and the service stayed healthy during the settle window. It does NOT mean the graph ran to completion or that a trigger ever fired — the engine does not yet report per-graph execution state, so the poll loop reads global health counters only. A graph whose trigger fires after 30 seconds will produce exit 0 at around 8 seconds of settle with no work done.
Use one-shot mode only for graphs you are confident fire immediately and finish in a few seconds. For anything longer, for time-based triggers, or for any graph whose completion you need to verify, use sidecar mode and check your output artefacts directly.
docker run --rm \
-v /path/to/project:/workspace \
-e SUCCESSION_LICENSE_TOKEN=lt_... \
-e SUCCESSION_GRAPH=my-graph.json \
succession-runner
With Docker Compose
For a permanent deployment, a compose file keeps the configuration in one place and restarts the runner with the host:
services:
succession:
image: succession-runner
restart: unless-stopped
volumes:
- ./project:/workspace
environment:
SUCCESSION_GRAPH: my-graph.json
SUCCESSION_TIMEOUT: "0"
env_file:
- succession.env # holds SUCCESSION_LICENSE_TOKEN and secrets
Environment Variables
| Variable | Required | Default | Purpose |
|---|---|---|---|
SUCCESSION_LICENSE_TOKEN | yes | — | License Token from the desktop app (lt_...) |
SUCCESSION_GRAPH | yes | — | Path to the graph .json, relative to the workspace (or absolute) |
SUCCESSION_WORKSPACE | no | /workspace | Where your mounted project lives inside the container |
SUCCESSION_TIMEOUT | no | 600 | One-shot mode: max seconds to wait. 0 = sidecar mode, run until stopped |
SUCCESSION_SECRET_<NAME> | no | — | Injects a secret into the graph (see below) |
SUCCESSION_API_TOKEN | no | auto-generated | Internal service credential; set it only if an external tool must call the runner’s API |
Secrets
Graphs reference secrets as @secret.NAME (see Parameter Scripting). In the runner, secrets come from environment variables with the SUCCESSION_SECRET_ prefix:
docker run -d \
-e SUCCESSION_SECRET_SLACK_WEBHOOK=https://hooks.slack.com/... \
...
makes @secret.SLACK_WEBHOOK available inside the graph.
Handling secrets safely:
- Prefer
--env-file(or composeenv_file) over-eon the command line, so tokens and secrets don’t end up in shell history or CI logs - Environment values are visible to anyone who can run
docker inspecton the host — treat host access as secret access - Any script-executing node in a graph can read all injected secrets, not only the ones it references. Only run graphs you trust with the secrets you provide
File Access
The runner can only read and write inside the mounted workspace (and the container’s temporary directory). A graph cannot touch other paths, even if a node is configured with one — the same filesystem access policy you know from the desktop app, locked to the workspace.
Practical consequence: use paths under /workspace/... in your graph’s file nodes, and mount everything the graph needs into the workspace.
Trust caveat: script-executing nodes (Run Script, Execute Command, etc.) spawn subprocesses outside the file access policy — they can read and write any path the container user can reach, not just the workspace. They also inherit the full process environment, including SUCCESSION_LICENSE_TOKEN and the internal SUCCESSION_API_TOKEN — an untrusted graph can read and exfiltrate these values. License tokens are revocable and validation-only, but treat them as you would any credential. Only run graphs you trust with the access and credentials you provide.
Webhooks and External Access
A webhook trigger listens on its own Port, not on the service port. Set its Bind IP to 0.0.0.0 so it accepts connections from outside the container, then publish that port when starting the container:
docker run -d \
-p 8080:8080 \
-e SUCCESSION_GRAPH=my-graph.json \
-e SUCCESSION_TIMEOUT=0 \
-v "$PWD":/workspace \
succession-runner
A trigger with Port 8080 and Webhook Path /build is then reachable at http://<host>:8080/build. Webhook triggers that set the same Bind IP and port share it, so one published port serves all of them as long as their paths differ.
Exit Codes
| Code | Meaning |
|---|---|
| 0 | One-shot: graph deployed and ran. Sidecar: stopped cleanly |
| 1 | Graph reported an error in the health-check response (rare — the engine does not yet update this field per graph after deploy; will become more common when per-graph execution tracking lands) |
| 2 | Invalid input: graph file not found, or a bad environment value |
| 3 | The Succession service failed to start or stopped unexpectedly |
| 4 | Graph deployment failed — check the license token and the graph file |
| 124 | One-shot mode timed out |
Viewing Logs
docker logs my-pipeline
Service and node execution logs are printed at info level. To change verbosity, set -e RUST_LOG=debug (or warn) when starting the container.
Limitations
- No DCC integrations — nodes that drive Blender, Maya, Houdini, Unreal, Unity, Photoshop, or Substance need those desktop applications and are not available in a Linux container
- Custom Python nodes are not supported by the runner yet (they are disabled in the container configuration)
- One graph per container. Run several containers for several graphs — they don’t interfere with each other
Troubleshooting
“Graph deployment failed (check license token and graph file)”
The license token is missing, mistyped, expired, or revoked — or the graph file is not valid. Check docker logs for the specific license error, and verify the token in the desktop app’s Licensing section.
“Graph file not found”
The path in SUCCESSION_GRAPH doesn’t exist inside the container. Remember it resolves relative to the workspace: -v /my/project:/workspace plus SUCCESSION_GRAPH=graphs/build.json expects /my/project/graphs/build.json on the host.
Graph runs but files don’t appear
Check the node writes under /workspace/... — writes outside the workspace are blocked by the file access policy (look for access-denied entries in the logs).
Related Topics
- Licensing Guide - Plans and License Tokens
- Graph Deployment - Deploying graphs in the desktop app
- CLI Reference - The command line used inside the runner
- Parameter Scripting - Secrets and expressions in graphs