Run it for a team
Run Pistis for your team on one server with HTTPS, sign-in and Postgres.
The compose file in deploy/compose runs everything a team needs on one Docker host: HTTPS, a database and two Pistis servers that cover for each other. Then you set up sign-in, code hosts and agents in the web app.
Before you start
- A Linux host with Docker and compose
- A domain name pointing at the host, for a real certificate
Start it
- Get the compose file and create the settings file with its keys:
git clone https://github.com/akshay5995/pistis && cd pistis/deploy/compose
cp .env.example .env && sh keys.sh >> .env- Edit
.env. SetPISTIS_DOMAINto your domain,PISTIS_TLSto your email for a Let's Encrypt certificate, andPISTIS_MODELwith its provider's key (ANTHROPIC_API_KEYfor the one it starts with). You can also leave the key empty and paste it in the control center.PISTIS_VERSIONis the release to run. - Start it. Compose pulls that release's images from GitHub's container registry:
docker compose up -d- Find the setup link in the logs of the two Pistis servers,
brain1andbrain2(a brain is a Pistis server process):
$ docker compose logs brain1 brain2 | grep "setup link"
brain1-1 | pistis serve: no administrator yet — setup link https://pistis.example.com/link/8a8b…#k=rK4z…- Open the link and type your name. You are the first administrator. The link works once, for an hour.
Set it up in the control center
As an admin, click Control center in the sidebar. Its first page lists what's left to set up, with a button for each step:
- Connect a model provider. Paste an API key on
Models→Connect a provider. Its models can be picked from the next session on, with no restart. Keys are encrypted withPISTIS_SECRET_KEYand never shown again. - Connect a code host.
Source control→Add GitHub App. See Connect GitHub. - Invite your team. Add a sign-in method (
Sign-in→Add OpenID ConnectorSign-in→Add GitHub), then let your colleagues in with your email domain. See Sign-in and people. - Run a first session.
Startopens a new session with a one-line task filled in. It needs a model provider but no repository.
The same page then shows what runs now, which sessions wait for someone's approval or answer, and tokens and spend over the last two weeks. Usage breaks spend down by person and by model, Fleet lists the Pistis servers and each live session's sandbox, and People lists everyone with their role.
Pick a model
.env starts with PISTIS_MODEL=anthropic/claude-sonnet-5-5 and an empty ANTHROPIC_API_KEY. Every session gets that model by default while its provider has a key, else the first model that has one. Set PISTIS_MODEL=provider/model-id and run docker compose up -d again to change the default. A key in .env works as well as one pasted in the control center. With no key at all, the web app's first screen asks for one and sessions don't start.
People can switch a session to any model from a provider with a key. To choose which ones they see, open Models, untick the ones to hide under Choose what people can pick and click Save. A model from a key you add later is offered until you untick it. Sessions already on a model you hide keep it; nobody can switch to it.
What runs
| Service | What it does |
|---|---|
caddy | HTTPS in front of everything |
brain1, brain2 | Two Pistis servers. Both serve every session. |
postgres | Sessions, people, connections, agents and saved files |
relay | The point sandboxes connect to. Each sandbox gets its own network, shared only with this service. |
docker-proxy | The only service with access to Docker. It lets Pistis manage its own sandboxes and nothing else. |
Keep .env private: it holds the keys. docker compose down and up keep all data, and running sandboxes reconnect. To move to a new release, see Upgrade.
Images
Each release is published as four images on GitHub's container registry, for amd64 and arm64, tagged with its version:
| Image | What it is |
|---|---|
ghcr.io/akshay5995/pistis | The Pistis server. The docker-proxy service runs it too. |
ghcr.io/akshay5995/pistis-relay | The relay, where sandboxes connect |
ghcr.io/akshay5995/pistisd | The default sandbox: Debian with git |
ghcr.io/akshay5995/pistis-browser | A sandbox with Debian's Chromium, for the browser |
Compose takes the version from PISTIS_VERSION and the registry from PISTIS_REGISTRY in .env. Set PISTIS_SANDBOX_IMAGE to run sessions on another image, such as the browser one or your own.
To build the images yourself instead, run pnpm install && pnpm images in the repository (it needs Node 24, pnpm 10 and Bun). It also writes docker-compose.override.yml next to the compose file, which compose reads on its own, so docker compose up -d runs your builds. Delete that file to go back to the published images.
If a server dies
The other Pistis server takes over its sessions within seconds. A task that was running finishes there. A command that was cut off is not run again; the agent is told. The sandbox kept running, so its files are still there.
Run a single process instead
Without compose, pistis serve runs Pistis from one config file:
PISTIS_SECRET_KEY=… DATABASE_URL=… pnpm pistis serve --config pistis.jsonSee Configuration for every key.