# Security

> Credentials, HTTPS, sign-in and network exposure of a PentAGI installation.

## [Change the defaults](https://pentagi.com/docs/configuration/security/#change-the-defaults)

A fresh installation creates the local administrator `admin@pentagi.com` with the password `admin`, which must be changed at first sign-in. If the password is lost, the installer's maintenance menu resets it as long as the account still uses the `admin@pentagi.com` address.

Set these values in `.env` before the first start; the installer generates the salt and the passwords for you. PostgreSQL and Neo4j take their credentials only when they create their data volumes, so changing them later breaks the connection:

| Variable                                             | Purpose                                                                                                   |
| ---------------------------------------------------- | --------------------------------------------------------------------------------------------------------- |
| `COOKIE_SIGNING_SALT`                                | Signs session cookies and API tokens — set a random value                                                 |
| `PENTAGI_POSTGRES_USER`, `PENTAGI_POSTGRES_PASSWORD` | PostgreSQL credentials                                                                                    |
| `NEO4J_PASSWORD`                                     | Neo4j password for the [knowledge graph](https://pentagi.com/docs/glossary/#knowledge-graph); `NEO4J_USER` must stay `neo4j` |
| `PUBLIC_URL`                                         | The URL users open, for example `https://pentagi.example.com`                                             |

On a running installation, change a database password inside PostgreSQL or Neo4j first, then in `.env`.

## [HTTPS](https://pentagi.com/docs/configuration/security/#https)

PentAGI serves HTTPS on port 8443 with a self-signed certificate. To use your own, set `SERVER_SSL_CRT` and `SERVER_SSL_KEY` and mount the files in `docker-compose.yml`.

## [Users and sign-in](https://pentagi.com/docs/configuration/security/#users-and-sign-in)

There is no sign-up form. Administrators manage local users through the Users API (`/api/v1/users/`) from a signed-in browser session — an API token gets 403 there — and roles restrict what each user can see and change. Local users change their own email and password under **Settings → Account**.

With GitHub or Google sign-in configured, a login whose provider-verified email matches an existing account, local accounts included, signs into that account with its role; any other login gets a new account with the default user role. Every installation starts with the administrator `admin@pentagi.com`, so move it to an address you control under **Settings → Account** before you enable sign-in, and enable it only where new accounts are acceptable, for example with a Google Workspace app limited to your domain.

GitHub and Google sign-in are available through OAuth. Register an app with the callback `${PUBLIC_URL}/api/v1/auth/login-callback` and add its credentials:

```bash
PUBLIC_URL=https://pentagi.example.com
OAUTH_GITHUB_CLIENT_ID=your_github_client_id
OAUTH_GITHUB_CLIENT_SECRET=your_github_client_secret
```

## [Network exposure](https://pentagi.com/docs/configuration/security/#network-exposure)

By default the PentAGI web interface listens on `127.0.0.1` only. To reach it from other machines:

```bash
PENTAGI_LISTEN_IP=0.0.0.0
PENTAGI_LISTEN_PORT=8443
PUBLIC_URL=https://192.168.1.100:8443
CORS_ORIGINS=https://localhost:8443,https://192.168.1.100:8443
```

Use the real address in `PUBLIC_URL` and `CORS_ORIGINS`, never `0.0.0.0`. Recreate the containers with `docker compose up -d --force-recreate` and open port 8443 in the firewall.

Behind a reverse proxy, set `TRUSTED_PROXIES` to the proxy's address or CIDR, comma-separated. Otherwise every request seems to come from the proxy, and the sign-in limit per address — 30 failed attempts in five minutes, then a 15-minute lockout — is shared by all users.

Each [flow](https://pentagi.com/docs/glossary/#flow)'s [sandbox](https://pentagi.com/docs/glossary/#sandbox) container also publishes two ports for out-of-band callbacks, such as reverse shells. They come from the 2000 ports that start at `DOCKER_PORTS_BASE` (default `28000`) and are bound to `DOCKER_PUBLIC_IP`, the address the [agents](https://pentagi.com/docs/glossary/#agent) also give targets to call back to.

By default `DOCKER_PUBLIC_IP` is `0.0.0.0`: the ports listen on every interface of the Docker host, and the agents look up their public address themselves. Set it to a specific address only if the host owns that address and the targets can reach it; behind NAT, keep the default. Ports that Docker publishes bypass ufw and firewalld rules on the host, so restrict the range with a firewall in front of the host, such as a cloud security group, or with rules in Docker's `DOCKER-USER` chain.

`PROXY_URL` routes the backend's calls to model providers, the embedding provider, search APIs and the update check through a proxy, which helps isolate the installation from external networks. Self-hosted endpoints such as Ollama, vLLM or SearXNG go through it too, as there is no `NO_PROXY` exception, so the proxy must be able to reach them. The flows' sandbox containers, where the agents run their commands, the scraper, which opens web pages for the browser [tool](https://pentagi.com/docs/glossary/#tool), and the Graphiti service do not use it, so restrict their outbound traffic at the network level. Sign-in with GitHub or Google and calls to a Langfuse or OpenTelemetry endpoint outside the bundled stacks do not use it either, and the Docker daemon pulls images with its own proxy settings.

## [Update check](https://pentagi.com/docs/configuration/security/#update-check)

Within two minutes of starting and then every three hours, the server asks `update.pentagi.com` whether a newer build is available. The request carries the installation ID, the license key if one is set, the version and platform, and a summary of the installation: the configured provider and sign-in types, a few feature switches, counts of users, flows, [tasks](https://pentagi.com/docs/glossary/#task), containers, prompts, API tokens and [tool calls](https://pentagi.com/docs/glossary/#tool-call), and token and cost totals per provider type — no names, addresses, prompts or flow content. `UPDATE_CHECK_INTERVAL=0` turns it off. Each time the installer starts and after each action it runs, such as Apply Changes, Update, Start or Stop, it sends the installed images and the state of each stack, plus the same summary while PentAGI is running; `UPDATE_CHECK_INTERVAL` does not affect it.

> [!WARNING]
> The `pentagi` container runs as root because it manages containers through the Docker socket. For stronger isolation, run the tools on a separate [worker node](https://pentagi.com/docs/deployment/worker-node/).