# How to Configure Pentagi for Different Environments: A Complete Deployment Guide

> Easily configure Pentagi for development, production, or worker deployments. Learn to switch environments using .env files without code changes in this deployment guide.

- Repository: [VXControl/pentagi](https://github.com/vxcontrol/pentagi)
- Tags: how-to-guide
- Published: 2026-03-21

---

**Pentagi uses environment variables defined in [`backend/pkg/config/config.go`](https://github.com/vxcontrol/pentagi/blob/main/backend/pkg/config/config.go) to control all runtime behavior, allowing you to switch between development, production, and worker-node deployments by modifying a `.env` file without changing any source code.**

Pentagi (vxcontrol/pentagi) is an AI-powered security analysis platform that adapts its runtime behavior entirely through environment variables. Whether you are running local development containers, hardened production servers, or distributed worker-node architectures, you can configure Pentagi for different environments by adjusting values in a `.env` file and restarting the containers.

## Configuration Architecture

Pentagi’s configuration system is centralized in [`backend/pkg/config/config.go`](https://github.com/vxcontrol/pentagi/blob/main/backend/pkg/config/config.go). The application uses `github.com/joho/godotenv` to load variables from a `.env` file into a strongly-typed `Config` struct. Each field uses struct tags like `env:"SERVER_HOST"` and `envDefault:"0.0.0.0"` to map environment variables with sensible defaults.

During startup, the `ensureInstallationID` and `ensureLicenseKey` functions generate or validate a persistent installation identifier stored in `DataDir/installation_id`. Boolean feature flags such as `EXECUTION_MONITOR_ENABLED` and `AGENT_PLANNING_STEP_ENABLED` toggle optional subsystems without requiring code changes.

The [`docker-compose.yml`](https://github.com/vxcontrol/pentagi/blob/main/docker-compose.yml) file automatically injects these variables into containers via the `env_file: .env` directive, ensuring any configuration change is reflected immediately upon container restart.

## Environment-Specific Deployment Profiles

### Local Development

For development on a laptop with Docker, bind to all interfaces and enable verbose logging:

```dotenv

# .env.dev

DATABASE_URL=postgres://pentagiuser:pentagipass@localhost:5432/pentagidb?sslmode=disable
SERVER_HOST=0.0.0.0
SERVER_PORT=8080
DEBUG=true
COOKIE_SIGNING_SALT=dev-random-salt
OPEN_AI_KEY=sk-your-dev-key
DUCKDUCKGO_ENABLED=true
CORS_ORIGINS=*

```

**Key points:**
- `DEBUG=true` enables verbose logging for troubleshooting.
- `SERVER_HOST=0.0.0.0` combined with Docker port mapping (`0.0.0.0:8080:8080`) allows access from the host machine.
- `CORS_ORIGINS=*` prevents CORS blocks during frontend iteration.

Start the environment with:

```bash
docker compose -f docker-compose.yml up -d

```

### Production Deployment with TLS

For hardened production servers, enforce HTTPS and restrict CORS origins:

```dotenv

# .env.prod

DATABASE_URL=postgres://pentagi:strongpass@pgvector:5432/pentagidb?sslmode=require
SERVER_HOST=0.0.0.0
SERVER_PORT=8443
SERVER_USE_SSL=true
SERVER_SSL_CRT=/certs/pentagi.crt
SERVER_SSL_KEY=/certs/pentagi.key
COOKIE_SIGNING_SALT=prod-very-random-salt
PUBLIC_URL=https://pentagi.example.com
CORS_ORIGINS=https://pentagi.example.com
OPEN_AI_KEY=sk-prod-key
DUCKDUCKGO_ENABLED=true
GRAPHITI_ENABLED=true
LANGFUSE_BASE_URL=https://langfuse.example.com
LANGFUSE_PUBLIC_KEY=...
LANGFUSE_SECRET_KEY=...

```

**Critical requirements:**
- `SERVER_USE_SSL=true` forces the Go server to serve TLS using certificates mounted into the container.
- `PUBLIC_URL` and `CORS_ORIGINS` must contain the real hostname—never use `0.0.0.0` or wildcards in production, or browsers will reject the certificate.
- Enable observability stacks by setting `GRAPHITI_ENABLED` and Langfuse variables.

Deploy with a clean rollout:

```bash
docker compose -f docker-compose.yml down
docker compose -f docker-compose.yml -f docker-compose-observability.yml up -d

```

### External Network Access

When exposing Pentagi beyond localhost, adjust the binding IP and public URL:

```dotenv

# .env.external

PENTAGI_LISTEN_IP=0.0.0.0
PENTAGI_LISTEN_PORT=8443
PUBLIC_URL=https://203.0.113.42:8443
CORS_ORIGINS=https://localhost:8443,https://203.0.113.42:8443

```

After editing, force container recreation to apply network changes:

```bash
docker compose down && docker compose up -d --force-recreate

```

Open the firewall port (example for Ubuntu with UFW):

```bash
sudo ufw allow 8443/tcp

```

### Podman Rootless Configuration

Podman’s rootless mode cannot bind privileged ports below 1024. The scraper service defaults to port 443, which requires modification:

Update [`docker-compose.yml`](https://github.com/vxcontrol/pentagi/blob/main/docker-compose.yml) to expose port 3000 instead:

```yaml
scraper:
  expose:
    - "3000/tcp"
  ports:
    - "${SCRAPER_LISTEN_IP:-127.0.0.1}:${SCRAPER_LISTEN_PORT:-9443}:3000"

```

Configure the corresponding environment variables:

```dotenv
SCRAPER_PRIVATE_URL=http://someuser:somepass@scraper:3000/
LOCAL_SCRAPER_USERNAME=someuser
LOCAL_SCRAPER_PASSWORD=somepass

```

### Worker-Node Architecture

For high-security deployments using a controller/worker split, configure the controller to communicate with a remote Docker daemon:

```dotenv

# .env.worker-node (controller side)

DOCKER_HOST=tcp://worker-node.example.com:2376
DOCKER_TLS_VERIFY=1
DOCKER_CERT_PATH=/etc/docker/certs

```

On the worker node, start the Docker daemon with `--tlsverify` and mount the certificate directory into the controller container. The `pkg/docker` wrapper reads these variables automatically—no code changes are required.

## Programmatic Configuration in Go

You can load configuration programmatically using the same package:

```go
package main

import (
  "log"
  "github.com/vxcontrol/pentagi/backend/pkg/config"
)

func main() {
  cfg, err := config.NewConfig() // reads .env automatically
  if err != nil {
    log.Fatalf("failed to load config: %v", err)
  }

  // Access the public URL the server will advertise
  log.Printf("Pentagi will be reachable at %s", cfg.PublicURL)
}

```

This approach is used internally by [`backend/cmd/installer/main.go`](https://github.com/vxcontrol/pentagi/blob/main/backend/cmd/installer/main.go) to generate tailored `.env` files interactively during installation.

## Summary

- **Environment variables drive all behavior**: The `Config` struct in [`backend/pkg/config/config.go`](https://github.com/vxcontrol/pentagi/blob/main/backend/pkg/config/config.go) exposes every tunable parameter via `env` tags.
- **File-based configuration**: Create distinct `.env` files (`.env.dev`, `.env.prod`, `.env.worker`) and point Docker to the appropriate file for instant environment switching.
- **No code changes required**: Adjusting `SERVER_USE_SSL`, `DOCKER_HOST`, or `OLLAMA_SERVER_URL` and restarting containers adapts the system for local development, production TLS, or external worker nodes.
- **Feature flags**: Boolean variables like `EXECUTION_MONITOR_ENABLED` toggle advanced subsystems without rebuilds.
- **Installation persistence**: The system automatically generates and stores an installation ID in `DataDir/installation_id` for licensing tracking.

## Frequently Asked Questions

### How does Pentagi load environment variables?

Pentagi uses the `godotenv` library to read a `.env` file from the working directory, then parses each variable into the `Config` struct using reflection on `env:"VARIABLE_NAME"` tags. Default values are provided via `envDefault` tags, and the [`docker-compose.yml`](https://github.com/vxcontrol/pentagi/blob/main/docker-compose.yml) injects these into containers using the `env_file: .env` directive.

### Can I switch LLM providers without rebuilding the containers?

Yes. Changing `OPEN_AI_KEY`, `OLLAMA_SERVER_URL`, or `OLLAMA_SERVER_MODEL` in your `.env` file and restarting the containers redirects all agent traffic to the new provider immediately. The provider factory in [`backend/pkg/providers/provider.go`](https://github.com/vxcontrol/pentagi/blob/main/backend/pkg/providers/provider.go) reads these variables at startup and initializes the appropriate client.

### What is the difference between `SERVER_HOST` and `PENTAGI_LISTEN_IP`?

`SERVER_HOST` controls the network interface the Go HTTP server binds to inside the container (e.g., `0.0.0.0` for all interfaces). `PENTAGI_LISTEN_IP` is used specifically for external access configurations to define which IP the service advertises or binds to when operating behind firewalls or NAT.

### How do I enable the execution monitor for agent supervision?

Set `EXECUTION_MONITOR_ENABLED=true` along with limits like `EXECUTION_MONITOR_SAME_TOOL_LIMIT=5` and `EXECUTION_MONITOR_TOTAL_TOOL_LIMIT=10`. When agents exceed these thresholds, the system spawns a mentor agent to intervene, as implemented in the monitoring subsystem referenced by the configuration flags.