Skip to content

Install and operate ParleML

Time: about 20 minutes to read · You need: ParleML running (Run ParleML), and access to the server's Docker commands. You'll end with: a server you can back up, upgrade, sign agents into and open to a team.

Run ParleML starts ParleML on your own machine. This page is for the person who runs it for others: what the container keeps, how to back it up and upgrade it, how to put it behind a proxy, and which settings matter.

In short

  • Persist one volume, /app/data_root. It holds everything ParleML keeps.
  • Keep agent logins in their own volumes (/root/.codex, /root/.claude), or use API keys.
  • Behind a proxy, set PARLEML_PUBLIC_URL and PARLEML_OAUTH_ISSUER to the public address.
  • For a team, turn on sign-in and set PARLEML_MODE=prod.
  • No telemetry: only agents talk to their model provider, and HF_HUB_OFFLINE=1 makes the rest fully offline.

What runs in the container

One container serves everything on port 8000:

Path What it is
/ The web application
/api/ The API the application and your scripts call
/mcp The MCP server for your own agents
/docs The interactive API reference
/help/ This documentation, and the ML4, MLI and agent guides

The standard image is ghcr.io/parleml/parleml:0.8.0, about 7.7 GB once unpacked. It runs on CPU, includes the Codex and Gemini CLI agents, and uses Codex by default.

The data volume

Everything ParleML keeps lives in one directory, the data root. In the image it is /app/data_root. Mount a volume there, or everything is lost when the container is removed.

-v parleml-data:/app/data_root

To keep the data in a host directory instead, mount it and point PARLEML_DATA_ROOT at it:

-v /srv/parleml/data:/data -e PARLEML_DATA_ROOT=/data

What lives in the data root:

Path What it holds
workspaces/<workspace id>/ Each workspace's datasets, experiments, models, knowledge bases and published documents
catalog.db The index the lists and search read. Rebuild on Settings → Workspaces & data recreates it from the files.
config/ What Settings edits: connections, profiles, skill packs, your skill edits, and vault.json, the encrypted secrets
.secret_key The key that encrypts the vault and signs sign-in sessions
agents/ Agent sessions: transcripts and the agents' work files
mlflow/ MLflow runs, when there is no MLflow connection
uploads/ Files staged from the browser
users.json, api_tokens.json, user_prefs.json People, API tokens (hashed) and personal preferences
audit_events.jsonl, oauth/ The audit log and connected agents

Two things are not on the data volume:

  • Agent logins. Each CLI keeps its sign-in in its own home directory. See Agents and sign-in.
  • Model weights downloaded on first use. The image carries the default foundation-model weights. Others download the first time they are needed and stay in the container, so they download again after you recreate it. Settings → Diagnostics → Models on this server shows which are cached.

Back up and restore

Back up the whole data root, with ParleML stopped.

  1. Stop ParleML:

    docker stop parleml
    
  2. Copy the volume into an archive in the current directory:

    docker run --rm -v parleml-data:/data -v "$PWD":/backup \
      ghcr.io/parleml/parleml:0.8.0 tar czf /backup/parleml-data.tgz -C /data .
    
    docker run --rm -v parleml-data:/data -v "${PWD}:/backup" `
      ghcr.io/parleml/parleml:0.8.0 tar czf /backup/parleml-data.tgz -C /data .
    
  3. Start ParleML again:

    docker start parleml
    

To restore, stop ParleML and unpack the archive into an empty volume:

docker run --rm -v parleml-data:/data -v "$PWD":/backup \
  ghcr.io/parleml/parleml:0.8.0 tar xzf /backup/parleml-data.tgz -C /data

Keep the vault and its key together

config/vault.json holds every connection's secret and the key that pseudonymises identifier columns (card numbers, emails, phone numbers, IP addresses). A model that uses it scores only with the key it was fitted with. .secret_key decrypts the vault. Back up both together, and keep them out of shared backups. Losing either means refitting those models and entering every connection's secret again.

Your version

Help (?) → About ParleML shows the release, the commit and date the image was built from, and the versions of ml4, mli, the agent runtime, the MCP server and the engines underneath. Copy versions puts them on the clipboard for a support question. The release is the image tag, and the image carries it as a label too:

docker inspect --format '{{ index .Config.Labels "org.opencontainers.image.version" }}' parleml

ParleML, ml4 and mli are released together under one version number.

Upgrade

  1. Back up the data volume.
  2. Download the new image:

    docker pull ghcr.io/parleml/parleml:<new-version>
    

    <new-version> is the tag of the release you are moving to.

  3. Remove the old container. The data stays in the volume:

    docker rm -f parleml
    
  4. Start the new image with the same docker run options as before: the same volumes, ports and environment.

  5. Open Help (?) → About ParleML and check the version.

Memory and CPU

Give the container at least 8 GB of memory. Give it more for large datasets, foundation models, text embeddings and explanations of large ensembles, which can take several GB each.

Docker Desktop sets the limit under Settings → Resources. On Linux, set it on the container, for example:

docker run -d --name parleml -p 8000:8000 --memory 16g --cpus 8 \
  -v parleml-data:/app/data_root \
  ghcr.io/parleml/parleml:0.8.0

ParleML queues heavy work rather than running it all at once. By default it runs one heavy job (an experiment fit, an explanation or a batch score) per four cores, and one explanation at a time. Settings → Diagnostics shows the job slots. Each fit uses every core it is given, so more jobs at once usually slows them all. To change the slots, see Background jobs.

No telemetry, and running offline

ParleML sends nothing home. It has no telemetry, no usage reporting and no update checks, and it switches off those of the tools it runs on:

  • Libraries: MLflow and Hugging Face usage telemetry are off, and litellm uses its bundled price list instead of downloading one.
  • Agent CLIs: Codex analytics, Gemini CLI usage statistics, and Claude Code telemetry and error reporting are off, and so are their update checks.

The only traffic that leaves the container is what you choose:

Traffic When To keep it local
An agent's calls to its model provider During agent sessions Use a local model through Ollama or LM Studio
A model download The first time you use a model the image doesn't include, such as a text-embedding model Start the container with -e HF_HUB_OFFLINE=1 to forbid downloads
Your own connections Databases, an MLflow server or an embeddings provider you add Don't add them

Everything else runs with no network at all: data, training, the default foundation models (TabICL and Chronos-2 are in the image), explanations, scoring and this documentation.

Agents and sign-in

The image includes Codex and Gemini CLI. Each agent needs an API key or a subscription login. Run ParleML shows both for one machine.

API keys go in the container's environment. On a team server, use keys that belong to the team: every session on the server uses them.

Agent Variables
Codex OPENAI_API_KEY (or CODEX_API_KEY, CODEX_ACCESS_TOKEN)
Gemini CLI GEMINI_API_KEY (or GOOGLE_API_KEY; or Vertex AI with GOOGLE_GENAI_USE_VERTEXAI=true and GOOGLE_CLOUD_PROJECT)
Claude Code (extended image) ANTHROPIC_API_KEY (or ANTHROPIC_AUTH_TOKEN)
Cursor (extended image) CURSOR_API_KEY

A subscription login runs the agents on a ChatGPT, Claude or Google AI plan you already pay for, with no per-token bill. It is usually the cheapest choice for one person. The login is kept in the CLI's home directory inside the container. Mount a volume there so it survives an upgrade:

Agent Login volume Sign in with
Codex -v parleml-codex:/root/.codex docker exec -it parleml codex login --device-auth
Claude Code -v parleml-claude:/root/.claude docker exec -it parleml claude, then /login
Gemini CLI -v parleml-gemini:/root/.gemini docker exec -it parleml gemini, then Sign in with Google. An API key is simpler on a server.

Then open Settings → Agents. Each agent shows Ready and, under Signed in with, where its credential comes from. The key itself is never shown.

PARLEML_AGENTS_HOST_ADAPTER sets the agent a profile uses when it names none: codex-cli (the image's default), gemini-cli, claude-cli or cursor-cli.

Agent administrators can run programs on the server

An agent administrator can add a local (stdio) tool server, which the server starts as a process. With sign-in on, every ParleML administrator is an agent administrator, so give the role with care. In open mode, the anonymous user is an agent administrator only for requests from inside the container, never through the published port — so on your own machine Settings → Agents, Profiles, Skill packs and Connections stay closed. To open them from your browser, start the container with PARLEML_OPEN_MODE_AGENT_ADMIN=true. Anyone who can reach the port can then run programs on the server, so use it only where the port is yours alone (the default -p 8000:8000 on a laptop; publish it as -p 127.0.0.1:8000:8000 to keep it off the network), and turn on sign-in for a shared server instead.

The extended image

Some options are not in the standard image, because of their licence, the origin of their data, or their size. Build them on top of it with one command; the recipe ships inside the image:

docker run --rm ghcr.io/parleml/parleml:0.8.0 cat /opt/parleml/Dockerfile.extended \
  | docker build --build-arg WITH_CLAUDE=1 -t parleml-claude -
Option Build argument What it gives you Why it is not in the standard image
Claude Code WITH_CLAUDE=1 (CLAUDE_VERSION pins a release) Agent sessions on Claude Code Its licence grants no redistribution
Cursor WITH_CURSOR=1 Agent sessions on Cursor (needs CURSOR_API_KEY) Its licence grants no redistribution
Name corpus WITH_NAMES=1 Six features on name columns, such as a known first or last name and its country of origin The corpus comes from a leaked data set; installing it is your call
fast.ai WITH_FASTAI=1 The Neural net (fast.ai) model family Size

Add one --build-arg for each option you want; each defaults to 0. All four add about 1.5 GB. Then run your image in place of the standard one. For Claude Code as the default agent, add -e PARLEML_AGENTS_HOST_ADAPTER=claude-cli.

Details: installing other Python packages

Install into the application's own environment, in a Dockerfile FROM the ParleML image:

RUN pip --python /app/.venv/bin/python install <package>

A plain pip install goes to the system Python, which ParleML cannot see. Anything not in the table above is untested.

The recipe builds on the image it came from. To read it before you pull the image, open parleml.com/extend/Dockerfile.extended, the same file for version 0.8.0. Your extended image is for your own use: don't push it to a public registry, because the licences of Claude Code and Cursor don't allow redistributing them.

GPU

The published image runs on CPU. A GPU build of the image carries the CUDA build of PyTorch (about 6 GB more, about 14 GB in all), which speeds up foundation models and text embeddings. Run a GPU build with access to the host's GPUs:

docker run -d --name parleml -p 8000:8000 --gpus all \
  -v parleml-data:/app/data_root \
  <gpu-image>

<gpu-image> is the name of your GPU build. Settings → Diagnostics → Hardware shows whether ParleML sees the GPU.

IP geolocation (MaxMind)

Features that place an IP address on a map (country, city, network) need the MaxMind GeoLite2 databases. Their licence does not allow ParleML to ship them.

  1. Download GeoLite2-City.mmdb and GeoLite2-ASN.mmdb from your MaxMind account into one directory on the host, for example /srv/parleml/maxmind.
  2. Mount that directory at /data/maxmind:

    -v /srv/parleml/maxmind:/data/maxmind:ro
    
  3. Check it: http://<your-server>:8000/api/describe/domains says, for the ip domain, whether the data was found.

MAXMIND_DB_DIR already points at /data/maxmind. Without the files, IP columns still work, without the geolocation features.

Behind a reverse proxy

Keep the container listening on port 8000, and publish it on any host port with -p. A TLS proxy in front of it forwards to that port.

Then tell ParleML its public address:

Variable Set it to Why
PARLEML_PUBLIC_URL https://parleml.example.com The links agents give back open the web application here. Unset, ParleML uses each request's own address, which is wrong when the proxy rewrites the host.
PARLEML_OAUTH_ISSUER The same address Agent hosts such as claude.ai and ChatGPT discover ParleML's OAuth server from it.
PARLEML_CORS_ORIGINS The same address The browser origins allowed to call the API.

claude.ai and ChatGPT call ParleML from their own servers, so they need it on public HTTPS.

PARLEML_AGENTS_SESSION_MCP_URL is where the agents inside the container reach ParleML. Its default, http://127.0.0.1:8000/session-mcp/, is right as long as ParleML listens on port 8000 inside the container. If you change that port, set it (the trailing slash is required), and set PARLEML_API_BASE to the same address and port.

Sign-on and production mode

A fresh container runs in open mode: anyone who can reach it can use it. For a team:

  1. Turn on sign-in with your identity provider. Set up single sign-on walks through it.
  2. Set PARLEML_MODE=prod. The health check then hides the data root and library versions from callers who are not signed in, and sign-in cookies are sent over HTTPS only.
  3. List the administrators in PARLEML_ADMIN_EMAILS.

A complete team server, with the data in a host directory and MaxMind mounted:

docker run -d --name parleml -p 8000:8000 \
  -e PARLEML_MODE=prod \
  -v /srv/parleml/data:/data -e PARLEML_DATA_ROOT=/data \
  -v /srv/parleml/maxmind:/data/maxmind:ro \
  -e PARLEML_AUTH_REQUIRED=true \
  -e PARLEML_OIDC_ISSUER=https://login.example.com \
  -e PARLEML_OIDC_CLIENT_ID=<client-id> \
  -e PARLEML_OIDC_CLIENT_SECRET=<client-secret> \
  -e PARLEML_OIDC_REDIRECT_URI=https://parleml.example.com/api/auth/callback \
  -e PARLEML_ADMIN_EMAILS=[email protected] \
  -e PARLEML_CORS_ORIGINS=https://parleml.example.com \
  -e PARLEML_PUBLIC_URL=https://parleml.example.com \
  -e PARLEML_OAUTH_ISSUER=https://parleml.example.com \
  -e OPENAI_API_KEY=<team-openai-key> \
  ghcr.io/parleml/parleml:0.8.0

<client-id> and <client-secret> come from your identity provider, and <team-openai-key> is the team's key for Codex.

Details: the same server with Docker Compose
services:
  parleml:
    image: ghcr.io/parleml/parleml:0.8.0
    ports: ["8000:8000"]
    environment:
      PARLEML_MODE: prod
      PARLEML_AUTH_REQUIRED: "true"
      PARLEML_OIDC_ISSUER: https://login.example.com
      PARLEML_OIDC_CLIENT_ID: <client-id>
      PARLEML_OIDC_CLIENT_SECRET: <client-secret>
      PARLEML_OIDC_REDIRECT_URI: https://parleml.example.com/api/auth/callback
      PARLEML_ADMIN_EMAILS: [email protected]
      PARLEML_CORS_ORIGINS: https://parleml.example.com
      PARLEML_PUBLIC_URL: https://parleml.example.com
      PARLEML_OAUTH_ISSUER: https://parleml.example.com
      OPENAI_API_KEY: <team-openai-key>
    volumes:
      - parleml-data:/app/data_root
      - parleml-codex:/root/.codex
      - /srv/parleml/maxmind:/data/maxmind:ro
volumes:
  parleml-data:
  parleml-codex:

The most-used environment variables

Variable Default in the image What it does
PARLEML_DATA_ROOT /app/data_root Where everything is kept. Mount it.
PARLEML_MODE dev Set prod on a team server.
PARLEML_AUTH_REQUIRED false true makes every API and MCP call need a signed-in person or an API token.
PARLEML_OIDC_ISSUER, …_CLIENT_ID, …_CLIENT_SECRET, …_REDIRECT_URI unset Single sign-on with your identity provider.
PARLEML_ADMIN_EMAILS empty Comma-separated emails that become administrators when they sign in.
PARLEML_OPEN_MODE_AGENT_ADMIN false Open mode only: lets the browser manage agent settings through the published port. Anyone who can reach the port can then run programs on the server.
PARLEML_CORS_ORIGINS http://localhost:5173 Browser origins allowed to call the API. It cannot be * while sign-in is required.
PARLEML_PUBLIC_URL each request's address The public address of the web application.
PARLEML_OAUTH_ISSUER each request's address The public address agent hosts use for OAuth.
PARLEML_AGENTS_HOST_ADAPTER codex-cli The default agent.
PARLEML_AGENTS_SESSION_MCP_URL http://127.0.0.1:8000/session-mcp/ Where agents inside the container reach ParleML.
PARLEML_MAX_UPLOAD_MB 512 The largest single upload, in MiB.
PARLEML_JOBS_HEAVY_CONCURRENCY 0 (one per four cores) Heavy jobs running at once.
MAXMIND_DB_DIR /data/maxmind Where the MaxMind databases are mounted.
ML4_PSEUDONYMISATION_KEY the key in the vault A pseudonymisation key of 32 characters or more. When set, it wins over the vault's.

Configuration and settings keys lists every setting, and the backend configuration reference lists every agent setting.

Next