curiosity

Curiosity Orchestrator

Many Studio instances.
One address.

The orchestrator runs each Studio instance as a Docker container and puts one address in front of them. It wakes a sleeping instance on the first visit and stops it again after an hour of no use.

A visit to a sleeping Studio instance A browser asks for the address of the instance acme. The orchestrator’s proxy reads the slug. The instance is asleep, so a starting page wakes it. When it is ready the proxy forwards the request and the visitor lands where they pointed. BROWSER/acme/OR ACME.HOSTGET /ACME/WAITINGOPENS01 · ORCHESTRATORSTARTING PAGEWakes itThen opens itSTARTING PAGEOn standbyPROXYSLUG ACMEReads the slugIDLE STOP60 minutes02 · INSTANCESbetaRUNNINGlabsSLEEPINGacmeSLEEPINGSTARTINGRUNNINGdemoSLEEPING
A visit to a sleeping Studio instance A browser asks for the address of the instance acme. The orchestrator’s proxy reads the slug. The instance is asleep, so a starting page wakes it. When it is ready the proxy forwards the request and the visitor lands where they pointed. BROWSER/acme/ or acme.hostOPENSWAITING01 · ORCHESTRATORSTARTING PAGEWakes itThen opens itSTARTING PAGEOn standbyPROXYReads the slugSLUG ACME02 · INSTANCESacmeSLEEPINGSTARTINGRUNNINGbetaRUNNINGlabsSLEEPINGdemoSLEEPING

06 · The visitor lands where they pointed

Runs Studio in Docker Routes /slug/ and slug.host Idle stop 60 minutes by default Keep warm Up to 7 days

What it does

A Studio for every team, on one machine

Each instance keeps its own data and its own sign in. The orchestrator does the rest.

01

One address in front

A landing page lists the published instances. /acme/ and acme.example.com both reach the instance named acme, over HTTP and websockets.

02

Sleeps when nobody uses it

An instance with no traffic for an hour is stopped. Opening it starts it again, and the starting page takes you in when it is ready.

03

One console for all of them

Create, start, stop, restart and delete instances. Update their image, back up their data, read their logs and watch CPU, memory, network and disk.

04

On a host you control

It runs with Docker on your machine. Each instance keeps its data in its own Docker volume. HTTPS comes from your certificate, a self signed one or Let’s Encrypt.

Sleep and wake

An instance nobody uses stops, and wakes when somebody does

Idle time, keep warm and capacity are settings, not scripts. Pick a step to stop the drawing and read it.

One Studio instance over time An instance runs while it is used, sits idle for 60 minutes, and is stopped and sleeps. A visit starts it again and it runs. A second bar shows keep warm: the instance held running for up to seven days. INSTANCENOT TO SCALERUNNINGIDLE 60 MINSLEEPINGSTARTINGRUNNINGA VISITKEPT WARMKEEP WARM · UP TO 7 DAYSThe idle clock does not stop it, and a crash does not end it.
One Studio instance over time An instance runs while it is used, sits idle for 60 minutes, and is stopped and sleeps. A visit starts it again and it runs. A second bar shows keep warm: the instance held running for up to seven days. INSTANCENOT TO SCALERunningEvery request counts as useIdle60 minutes without trafficSleepingStopped, data kept in its volumeA visit wakes itThe starting page keeps askingRunning againThe idle clock starts overKEEP WARM · UP TO 7 DAYSHeld running, and started again if stopped.
  1. 01

    It runs while it is used

    Every request counts as activity, and a request in progress, an upload or a download, keeps the instance up. A tab left open does not.

  2. 02

    Nobody uses it for an hour

    After ORC_IDLE_TIMEOUT_MINUTES without traffic, 60 by default, the orchestrator stops the instance.

  3. 03

    It sleeps

    The stop is graceful: Studio saves its graph on the way down, so a stop can take up to 10 minutes. The data stays in its Docker volume.

  4. 04

    A visit wakes it

    Opening it in the browser shows the starting page, which starts the instance and keeps asking until it is ready.

  5. 05

    It is running again

    The visitor lands on the address they asked for. The idle clock starts again.

  6. 06

    Or keep it warm

    Keep warm holds an instance running for up to 7 days. It is a guarantee: one found stopped, after a crash or a reboot, is started again.

One address

The first word names the instance

A path or a subdomain, the same instance. Cookies and redirects are re-scoped to /{slug}/, so instances on one host do not overwrite each other’s sign in.

example.com/aviation/search

The instance aviation, at /search.

aviation.example.com/search

The same instance, at the same /search. The first label of the host names it.

example.com/ and www.example.com/

The orchestrator’s own landing page.

nothing-by-this-name.example.com/

The orchestrator again, because no instance has that name.

Subdomains need a wildcard DNS record and a certificate that covers it. Switch subdomain routing off and the path address is all there is.

Management console

One console, every instance

Password protected, at /#/manage. Everything you would do to a container by hand, with the usage beside it.

  • Create, start, stop, restart and delete instances
  • Update an image, or every outdated one at once
  • Keep an instance warm for up to 7 days
  • Back up, restore or reset an instance’s data
  • CPU, memory, network and disk, per instance and for the host
  • Container logs, the activity history and the effective settings

Fleet

Add machines when one is not enough

A central orchestrator manages nodes on other machines. Each node runs its instances exactly as a standalone one does, and keeps running them if the central goes away.

A central orchestrator and three nodes A central orchestrator, with three nodes below it. A new node starts and waits, then the central approves it. An instance, acme, is created on node A. Visitors reach it through the central. Then it is moved to node C. BROWSER/acme/CENTRALConsole and front doorNODE AbetaRUNNINGNODE BlabsSLEEPINGNODE CPENDINGWaiting for approvalNODE CACTIVEacme
A central orchestrator and three nodes A central orchestrator, with three nodes below it. A new node starts and waits, then the central approves it. An instance, acme, is created on node A. Visitors reach it through the central. Then it is moved to node C. CENTRALConsole and front doorNODE AbetaRUNNINGNODE BlabsSLEEPINGNODE CPENDINGWaiting for approvalNODE CACTIVEVISITORS: /ACME/acme
  1. 01

    A node starts

    Run the orchestrator with ORC_ROLE=node on another machine. It prints an enrollment code and waits.

  2. 02

    The central approves it

    Add it by address with the code, or let it join with a one time token. Every call after that is signed with a secret of its own.

  3. 03

    Create an instance on a node

    Pick a node for a new instance, or let the central choose the one with the most free memory.

  4. 04

    One address for visitors

    Visitors open /{slug}/ or {slug}.{host} on the central, which forwards to the node.

  5. 05

    Move it to another node

    A move stops the instance, copies its data across and starts it on the other node, keeping what is left of a keep warm.

Install

Run it on your own machine

One command, then one with a password. The release is self contained. All it needs is Docker.

macOS · Linux

01 · Install

Downloads the latest release for your machine, checks its SHA-256 and unpacks it into ~/.curiosity/orchestrator. A launcher goes in ~/.curiosity/bin, and your shell profile gets that folder on its PATH. Docker is not installed for you.

Terminal
 curl -fsSL https://raw.githubusercontent.com/curiosity-ai/orchestrator/refs/heads/main/install.sh | sh

02 · Start it

Start it with a management password. Data goes to ./storage unless ORC_STORAGE names a folder, so set it for anything beyond a try out.

Terminal
 ORC_ADMIN_PASSWORD='choose-a-password' ORC_STORAGE="$HOME/.curiosity/orchestrator-data" curiosity-orchestrator

What you see

Example session · what the installer prints
 curl -fsSL https://raw.githubusercontent.com/curiosity-ai/orchestrator/refs/heads/main/install.sh | shInstalling the Curiosity Orchestrator (linux-x64)  downloading v26.10.6452: https://github.com/curiosity-ai/orchestrator/releases/download/v26.10.6452/curiosity-orchestrator-26.10.6452-linux-x64.tar.gz  sha256 verified  installed /home/you/.curiosity/orchestrator  launcher  /home/you/.curiosity/bin/curiosity-orchestrator  added /home/you/.curiosity/bin to PATH in /home/you/.bashrc The Curiosity Orchestrator v26.10.6452 is installed.Open a new terminal, or run this one first:  export PATH="/home/you/.curiosity/bin:$PATH"Then start it with a management password (data goes to ./storage unless ORC_STORAGE says otherwise):  ORC_ADMIN_PASSWORD='choose-a-password' ORC_STORAGE="$HOME/.curiosity/orchestrator-data" curiosity-orchestrator ORC_ADMIN_PASSWORD='choose-a-password' curiosity-orchestrator

Read the script · Install in the README

Windows

01 · Install

Downloads the latest release, checks its SHA-256 and unpacks it into %USERPROFILE%\.curiosity\orchestrator. The folder is added to your user PATH. Docker Desktop is not installed for you.

PowerShell
 irm https://raw.githubusercontent.com/curiosity-ai/orchestrator/refs/heads/main/install.ps1 | iex

02 · Start it

Start it with a management password. To upgrade later, stop it first: Windows locks the folder of a running program.

PowerShell
 $env:ORC_ADMIN_PASSWORD = 'choose-a-password'; $env:ORC_STORAGE = "$HOME\.curiosity\orchestrator-data"; curiosity-orchestrator

What you see

Example session · what the installer prints
 irm https://raw.githubusercontent.com/curiosity-ai/orchestrator/refs/heads/main/install.ps1 | iexInstalling the Curiosity Orchestrator (win-x64)  downloading v26.10.6452: https://github.com/curiosity-ai/orchestrator/releases/download/v26.10.6452/curiosity-orchestrator-26.10.6452-win-x64.zip  sha256 verified  installed C:\Users\you\.curiosity\orchestrator The Curiosity Orchestrator v26.10.6452 is installed.Start it with a management password (data goes to .\storage unless ORC_STORAGE says otherwise):  $env:ORC_ADMIN_PASSWORD = 'choose-a-password'; $env:ORC_STORAGE = 'C:\Users\you\.curiosity\orchestrator-data'; curiosity-orchestrator $env:ORC_ADMIN_PASSWORD = 'choose-a-password'; curiosity-orchestrator

Read the script · Install in the README

Docker

01 · The Dockerfile

The orchestrator also runs as a container, and needs the Docker socket to manage the instances’ containers. This builds an image from a release.

Dockerfile
FROM mcr.microsoft.com/dotnet/runtime-deps:10.0
ARG VERSION
ARG RID=linux-x64
ADD https://github.com/curiosity-ai/orchestrator/releases/download/v${VERSION}/curiosity-orchestrator-${VERSION}-${RID}.tar.gz /tmp/orchestrator.tar.gz
RUN tar -xzf /tmp/orchestrator.tar.gz -C /opt \
 && mv /opt/curiosity-orchestrator-${VERSION}-${RID} /app \
 && rm /tmp/orchestrator.tar.gz
WORKDIR /app
ENV ORC_STORAGE=/data \
    ORC_CONTAINER_ACCESS=network
VOLUME /data
EXPOSE 8080 443
ENTRYPOINT ["./curiosity-orchestrator"]

02 · The compose file

Next to it. This serves HTTPS with a self signed certificate. For Let’s Encrypt, the README has the settings.

docker-compose.yml
services:
  orchestrator:
    build:
      context: .
      args:
        VERSION: 26.10.6452    # a release from the GitHub releases page
        RID: linux-x64         # linux-arm64 on an Arm host
    image: curiosity-orchestrator
    restart: unless-stopped
    environment:
      - ORC_ADMIN_PASSWORD=${ORC_ADMIN_PASSWORD:?Set ORC_ADMIN_PASSWORD}
      - ORC_PUBLIC_ADDRESS=${ORC_PUBLIC_ADDRESS:-https://localhost}
      - ORC_CERT_SELF_SIGNED=true
      - ORC_PORT=443
      - ORC_PORT_LOCAL=8080
      - ORC_REDIRECT_TO_HTTPS=true
    ports:
      - "443:443"
      - "80:8080"
    volumes:
      - orchestrator-data:/data
      - /var/run/docker.sock:/var/run/docker.sock
    stop_grace_period: 1m

volumes:
  orchestrator-data:

What you see

Example session · starting the container
 ORC_ADMIN_PASSWORD='choose-a-password' docker compose up -dOpen https://localhost/#/manage and sign in as admin.

Docker in the README

To upgrade, run the script again. It replaces the program and leaves your data, which lives under ORC_STORAGE. Settings, all optional: ORC_VERSION for a release other than the latest, ORC_INSTALL for another folder, ORC_NO_MODIFY_PATH=1 to leave your PATH alone.

Your first instance

From install to a running Studio

  1. 01

    Start it

    Run the orchestrator with a password. It listens on port 8080 and keeps its data in ./storage unless ORC_STORAGE says otherwise.

  2. 02

    Create an instance

    Open localhost:8080/#/manage, sign in as admin and create an instance named acme. The first time, it pulls the Curiosity image, which takes a while.

  3. 03

    Open it

    Go to localhost:8080/acme/, or acme.localhost:8080. Browsers resolve *.localhost to your own machine.

Operations

What you would otherwise write scripts for

HTTPS, backups, updates and limits are part of the console and its API.

HTTPS

Your own certificate, a self signed one, or certificates from Let’s Encrypt. They renew 30 days before expiry, and each instance gets one for its subdomain.

Backups

Download an instance’s data as a .tar.gz, restore it into the same or another instance, or reset it to empty. A restore is checked in full before anything is deleted.

Updates

Update an instance’s image one at a time, or every outdated one at once. The data stays in its volume.

Scripting

Set ORC_API_TOKEN and the management API takes a bearer token, so a backup is one curl call.

Capacity

Set the most instances that may run at once. Waking one on a full host stops the one used least recently, if nobody is using it.

Logs and usage

Container logs with follow, filter and download. CPU, memory, network and disk per instance and for the host, with history.

Security

What to know before you expose it

The README says where the trust boundaries are. So does this page.

01

Console sign in

The session cookie is HttpOnly and SameSite strict, and failed sign ins are throttled. The API token grants the same access as the console.

02

A host of its own for the console

Instances on paths share the orchestrator’s origin. Where instance administrators are not fully trusted, set ORC_MANAGEMENT_HOST and the console answers only there.

03

Subdomains give each instance an origin

Opening an instance on its subdomain keeps its pages apart from the console and from the other instances.

04

The Docker socket is root equivalent

The orchestrator needs it to manage containers, and ORC_STORAGE holds each instance’s administrator password. Protect both like secrets.

FAQ

Questions about the orchestrator

What does the orchestrator need to run?

Docker on the host. The releases are self contained, so no .NET installation is needed. The install script covers Linux, macOS and Windows, and warns you when it cannot find Docker.

How is it different from running Studio in Docker myself?

One container is one container. The orchestrator is for several: it puts them behind one address, starts and stops them as they are used, updates their images, backs up their data and shows their usage.

What happens to an instance’s data when it sleeps?

It stays in the instance’s Docker volume. Stopping is graceful, because Studio saves its graph on the way down, so a stop can take up to 10 minutes. Updating the image or changing limits re-creates the container and never touches the volume.

Does a background request wake a sleeping instance?

No. Opening it in the browser wakes it. A background request, such as an API call or a stale tab polling, gets a 503. A tab left open does not keep an instance awake either.

How do I keep an instance running?

Keep it warm for up to 7 days. It is a guarantee: a kept warm instance that is found stopped, after a crash or a reboot, is started again. Stopping it from the console clears it.

Can I use my own domain and certificate?

Yes. Provide a certificate file, let the orchestrator generate a self signed one, or let Let’s Encrypt issue and renew them. Subdomain addresses need a wildcard DNS record and a certificate that covers it. With subdomain routing off, only the path address is served.

Can several machines serve one set of instances?

A central orchestrator can manage nodes on other machines and serve all their instances from one address. It calls each node by its address, so a node behind NAT is not supported yet.

Can I script it?

Yes. Set ORC_API_TOKEN, 24 characters or more, and send it as a bearer token. The management API then does what the console does, including backup and restore.

Your data. Your infrastructure.

Give every team a Studio.
Keep one address.