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

Pentagi uses environment variables defined in 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. 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 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:


# .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:

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

Production Deployment with TLS

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


# .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:

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:


# .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:

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

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

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 to expose port 3000 instead:

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

Configure the corresponding environment variables:

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:


# .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:

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 to generate tailored .env files interactively during installation.

Summary

  • Environment variables drive all behavior: The Config struct in 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 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 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.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →