# Production

> Running PentAGI for a team — hardening, isolation, Podman and several instances.

## [Checklist](https://pentagi.com/docs/deployment/production/#checklist)

* Set every credential, `COOKIE_SIGNING_SALT` included, before the first start — see [Security](https://pentagi.com/docs/configuration/security/). The installer generates the salt and the service passwords, but not the Langfuse and Grafana admin passwords: set `LANGFUSE_INIT_USER_PASSWORD`, `password` in the template, before Langfuse first starts, and change Grafana's default `admin` / `admin` after its first start. On a running installation, change the PostgreSQL and Neo4j passwords inside the databases before you change them in `.env`.
* Serve a real certificate and a stable `PUBLIC_URL`.
* Behind a reverse proxy, set `TRUSTED_PROXIES` to the proxy's address or CIDR. Otherwise every user shares the proxy's address, and 30 failed sign-ins within 5 minutes lock everyone out for 15 minutes.
* Move [tool](https://pentagi.com/docs/glossary/#tool) execution to a dedicated [worker node](https://pentagi.com/docs/deployment/worker-node/).
* Enable [observability](https://pentagi.com/docs/configuration/observability/) so you can follow cost and failures.
* Keep the [knowledge graph](https://pentagi.com/docs/glossary/#knowledge-graph) and Langfuse on a private network.

## [Podman](https://pentagi.com/docs/deployment/production/#podman)

PentAGI runs on Podman as well as Docker. In rootless mode the `scraper` service needs extra configuration because rootless containers cannot bind privileged ports; the repository README describes the rootless and rootful setups.

## [Several instances (`TENANT_ID`)](https://pentagi.com/docs/deployment/production/#several-instances-tenant_id)

Leave `TENANT_ID` empty for a single installation, and keep it empty on an existing one: setting it later moves the instance to a new, empty schema that starts with the default `admin@pentagi.com` account, and its [flows](https://pentagi.com/docs/glossary/#flow), users and settings no longer appear. Set it on the instances you add when several PentAGI instances share external resources such as one PostgreSQL server, one [worker node](https://pentagi.com/docs/glossary/#worker-node), one Neo4j or one Langfuse:

| Area              | Effect of `TENANT_ID=acme`                                         |
| ----------------- | ------------------------------------------------------------------ |
| PostgreSQL        | Works inside schema `acme` instead of `public`                     |
| Worker containers | Named `acme-pentagi-terminal-<flow>`                               |
| Knowledge graph   | Group ids become `acme-flow-<id>`                                  |
| Auth              | Cookie and token keys include the [tenant](https://pentagi.com/docs/glossary/#tenant) |
| Telemetry         | Langfuse and OpenTelemetry data are tagged with the tenant         |

The value must match `^[a-z][a-z0-9_]{0,31}$`. Host resources are not namespaced. Instances on one server need their own `DATA_DIR` and published ports. Instances whose [sandboxes](https://pentagi.com/docs/glossary/#sandbox) run on the same Docker host, on one server or a shared worker node, need their own `DOCKER_PORTS_BASE` and, if it is set, their own `DOCKER_WORK_DIR`; otherwise their sandboxes claim the same ports and flows fail to start. Each base starts a window of 2000 ports, `28000` by default, so use for example `28000` and `30000`.