Skip to content

Local container setup

One script builds the server from your working tree and starts the whole stack. You get Pia Server, its database migrations, PostgreSQL, pgvector, Temporal, the file host and the buyer portal. The server answers at https://localhost:8081.

  • Podman 5 with a running machine, plus a compose provider. Set up the machine once with podman machine init and podman machine start, then install the provider with winget install Docker.DockerCompose.
  • Or Docker with the compose plugin.
  • PowerShell 7.2 or later (pwsh).

If both engines are installed, the script uses Podman. Set PIA_CONTAINER_CLI=docker to use Docker instead. If the Podman machine is stopped, the script starts it for you.

Everything lives in deploy/local/.

File Purpose
compose.yml The compose file for the whole stack
pia-stack.ps1 Script for up, status, logs, psql, down, reset and e2e
env.example Template for optional overrides
.env Your overrides, copied from env.example. Optional and gitignored
.state/ Generated secrets, certificate and license. Gitignored

You don’t need to generate any keys. On the first up, the script creates the JWT key, the encryption key and the database passwords in deploy/local/.state/pia/stack.env. It also creates a self-signed HTTPS certificate. These secrets are created once and never rotated, because the data volumes depend on them.

Service What it is
pia-server Pia Server
pia-migrate One-shot container that applies the database migrations
postgres PostgreSQL for the server, the portal and Temporal
pia-vectordb PostgreSQL with pgvector, for knowledge bases
temporal, temporal-ui Temporal server (temporalio/server on the local PostgreSQL) and its web UI
temporal-db-init, temporal-schema-init, temporal-namespace One-shot setup containers for Temporal
pia-storage The file host
pia-portal, pia-portal-init The buyer portal and its database setup
pia-license-seed Copies your license into the server’s data volume
Service Port
Server (HTTPS) 8081
Server (HTTP, redirects to HTTPS) 8080
Storage 8090
Portal 8095
Temporal UI 8233
PostgreSQL 5432
pgvector 5433

Without a license, every /admin page redirects to /admin/setup. The stack builds in Debug, so it needs a license signed with the DEBUG key. The script takes the first one it finds:

  1. The file in PIA_LICENSE_FILE
  2. artifacts/local_dev_cloud_1_kb.xml
  3. The license already in deploy/local/.state/license/license.lic

It copies the license into the server on first start. If you replace the license later in the admin console, your new one stays.

  1. Optional: create your overrides

    Terminal window
    Copy-Item deploy/local/env.example deploy/local/.env

    Set only what you need, such as an AI provider key or OAuth credentials. You can skip this step and start without it.

  2. Start the stack

    Terminal window
    pwsh deploy/local/pia-stack.ps1 up

    The script builds the images from your working tree, starts every service and waits until the stack is healthy.

  3. Check it

    Terminal window
    pwsh deploy/local/pia-stack.ps1 status
    curl.exe -k https://localhost:8081/health

    Then open https://localhost:8081/admin in your browser.

The AI proxy needs at least one upstream provider to be useful. Set these in deploy/local/.env.

Variable Example
AI_PROVIDER_TYPE OpenAI (the default)
AI_API_KEY sk-proj-...
AI_MODEL gpt-4o-mini
AI_ENDPOINT https://api.openai.com

Valid provider types are OpenAI, AzureOpenAI, Ollama, OpenRouter, OpenAICompatible, Mistral and VLlm.

You can also set a separate provider per client mode (Optimize / Assistant / Research). The client sends the active mode in the X-Pia-Mode header. Without a per-mode override, the default provider above is used.

Variable Purpose
AI_ASSISTANT_PROVIDER_TYPE / _API_KEY / _MODEL / _ENDPOINT Override for Assistant mode
AI_RESEARCH_PROVIDER_TYPE / _API_KEY / _MODEL / _ENDPOINT Override for Research mode

env.example lists more settings, such as the Azure deployment name and extra catalog providers.

To enable Google or Microsoft sign-in locally, set these in deploy/local/.env:

Variable What it is
OAUTH_GOOGLE_CLIENT_ID / OAUTH_GOOGLE_CLIENT_SECRET Google OAuth credentials
OAUTH_MICROSOFT_CLIENT_ID / OAUTH_MICROSOFT_CLIENT_SECRET Microsoft / Entra credentials

compose.yml already runs temporalio/server on the local PostgreSQL, but the operator runtime is off until you enable it:

Variable Default Purpose
OPERATORS_ENABLED false Master switch — restart-only
TEMPORAL_ADDRESS temporal:7233 Where the embedded worker connects
TEMPORAL_NAMESPACE pia
TEMPORAL_TASKQUEUE pia-operators

Every OPERATORS_* cap (MAXSTEPS, RETENTIONDAYS, and the rest) has a working default — see Configuration. Enabling this without a reachable Temporal is not a crash: the worker logs a warning and idles, and /health stays green.

Connector pods need no configuration here at all — they are catalog rows, created from Admin → Connectors once the server is up.

In Pia, open Settings → Account and set:

Setting Value
Server URL https://localhost:8081

Then choose Pia Cloud as your AI provider. The client will route to the server for /api/ai/optimize, /api/sync/push, and /api/sync/pull.

OAuth login buttons in the client only appear when the matching OAUTH_* credentials are set in deploy/local/.env.

Terminal window
pwsh deploy/local/pia-stack.ps1 up # Build from the working tree and start
pwsh deploy/local/pia-stack.ps1 status # Show the state of every service
pwsh deploy/local/pia-stack.ps1 logs pia-server # Follow one service; omit the name for all
pwsh deploy/local/pia-stack.ps1 psql # psql shell into the local database
pwsh deploy/local/pia-stack.ps1 down # Stop, keep the data
pwsh deploy/local/pia-stack.ps1 reset # Stop and delete the volumes

A second stack, pia-e2e, runs next to the dev stack for the automated browser tests. It uses ports in the 18xxx range, so both can run at the same time.

Terminal window
pwsh deploy/local/pia-stack.ps1 e2e

This starts a fresh pia-e2e stack, runs the test suite and removes the stack again on success. A failed run leaves the stack up so you can read its logs.

  • podman compose has no provider: install it with winget install Docker.DockerCompose.
  • Cannot connect to Podman: run podman machine start.
  • Port already allocated: another stack or a host service uses the port. Check the other stack with status, or stop it.
  • pia-server keeps restarting: run pwsh deploy/local/pia-stack.ps1 logs pia-server. Configuration errors stop the server at boot and are named in the log.
  • Admin redirects to /admin/setup: no license was found. See License.
  • AI proxy returns 503: AI_API_KEY is missing. Check GET /api/ai/status.
  • OAuth not working: confirm the redirect URI https://localhost:8081/auth/callback is registered with the provider, and that client ID and secret are in deploy/local/.env.