Self-hosting
Reference

Configure a self-hosted platform

Configure Agent Barn’s identity, databases, model proxy, Agent runtimes, networking, storage, email, integrations, background workers, and monitoring.

For
Platform engineers, self-hosted operators, and Kubernetes administrators
On this page
  1. Overview
  2. Configuration paths
  3. Configuration boundaries
  4. Before you begin
  5. 1. Create the configuration file
  6. 2. Configure identity and stable keys
  7. 3. Configure data services
  8. 4. Configure models and Agent runtimes
  9. 5. Configure URLs, DNS, and TLS
  10. 6. Configure Kubernetes access and storage
  11. 7. Configure optional integrations
  12. 8. Configure workers and Telemetry
  13. 9. Configure monitoring
  14. Separate production and staging
  15. Configuration variable reference
  16. Apply configuration changes
  17. Validate the configuration
  18. Security and rotation
  19. Current configuration constraints
  20. Troubleshooting
  21. Next steps
  • Self-hosting
  • Configuration
  • 18 minutes

Configure the services, credentials, networking, storage, and runtime settings a self-hosted Agent Barn installation requires.

Overview

This reference covers both supported configuration paths — a local Docker and k3d environment, and a persistent Kubernetes deployment using Helmfile. It prepares the configuration the deployment tools consume; Deploy Agent Barn to Kubernetes applies it to a cluster.

Configuration moves through five layers:

  1. Environment file A local, secret-bearing .env for Docker and k3d, or .env.deploy for Kubernetes. Neither file is committed.
  2. Deployment tooling run.sh and compose.yml locally, or deploy.sh and helmfile.yaml.gotmpl for Kubernetes.
  3. Kubernetes Secrets and Helm values The tooling maps environment variables into chart values and Secrets. A value only takes effect when something actually maps it.
  4. Platform services The Agent Barn API, UI, PostgreSQL releases, LiteLLM, Redis, Firecrawl, workers, and monitoring.
  5. Generated Agent workloads The API renders Deployments, Secrets, Services, ConfigMaps, and PVCs for each Agent when it starts.

The diagram reads top to bottom: an environment file feeds the deployment tooling, which produces Kubernetes Secrets and Helm values, which configure the platform services, which in turn generate each Agent’s workload.

Configuration has two different lifetimes:

Lifetime Examples
Platform configuration Database credentials, signing key, ingress hosts, email provider, registry, monitoring
Generated Agent configuration Runtime image, model proxy address, Ingest address, platform credentials, rendered Templates and Skills

Changing platform configuration does not necessarily rebuild an already running Agent. Generated Agent settings normally take effect the next time the Agent is stopped and started.

Configuration paths

Choose the file that matches how you run Agent Barn.

Local — .env

Copied from .env.spec at the repository root. Applied by ./run.sh and compose.yml, and read directly by the API, UI, worker, and Make targets during native development.

run.sh validates the variables the complete local stack requires, and exits listing any that are missing.

Kubernetes — .env.deploy

Copied from .env.deploy.spec. Applied by ./deploy.sh, which sources the file, derives POD_KUBECONFIG_B64 when it is omitted, applies the bootstrap RBAC manifest, and runs Helmfile.

Variable names and network addresses differ from the local file. Do not use .env as a production deployment file.

Environment Template Working file Applied by
Local Docker and k3d .env.spec .env ./run.sh and compose.yml
Local native development .env.spec .env API, UI, worker, and Make targets
Kubernetes .env.deploy.spec .env.deploy ./deploy.sh and helmfile.yaml.gotmpl
Kubernetes staging .env.deploy.spec .env.deploy.staging ENV_FILE=.env.deploy.staging ./deploy.sh

Configuration boundaries

Configuration is owned at several layers.

Layer Owns
Deployment environment Secrets, image versions, URLs, storage, registry access, and external-provider credentials
Helmfile Release order, and mapping environment variables to chart values
Helm charts Kubernetes Secrets, Deployments, Services, hooks, probes, ingress, worker, and reconciliation
API configuration Authentication, encryption, the model catalogue, runtime images, and integration clients
Organization settings Allowed models, Members, Templates, Skills, and Shared Credentials
Agent settings Runtime, model, chat platform, access policies, credentials, Skills, and the Template pin

Environment configuration should establish a secure platform baseline. Organization and Agent configuration belongs in the product’s authenticated workflows.

Before you begin

For local configuration

  • The public agent-barn repository
  • Docker with Linux containers
  • kubectl
  • An OpenRouter API key
  • Enough memory for the application, k3d, LiteLLM, and Agent runtimes
  • Compatible Hermes and OpenClaw image references
  • A GitHub token only when the local base-image build needs authenticated repository access

For Kubernetes configuration

  • The Agent Barn deployment files or release bundle
  • An existing Kubernetes cluster and a kubeconfig for it
  • Helm, Helmfile, and the Helm diff plugin
  • A registry holding compatible API, UI, Hermes, and OpenClaw images
  • Three DNS names: UI, API, and Grafana
  • Traefik and cert-manager
  • A usable StorageClass
  • OpenRouter, registry, monitoring, and database credentials

Create the configuration file

Local environment

From the repository root:

Copy the template
cp .env.spec .env

Open .env and replace the placeholder values. The full local launcher checks its required values before it creates the cluster or starts containers:

Start the stack
./run.sh

If a required value is missing, the script exits and lists the missing variable names.

Kubernetes environment

From the deployment directory:

Copy the template
cp .env.deploy.spec .env.deploy

Restrict access to the file:

Restrict permissions
chmod 600 .env.deploy

The file is sourced by a shell, so use plain assignments:

Assignment shape
KEY=value

Avoid spaces around =, shell command substitutions, values copied from examples, unescaped shell metacharacters, multiline secret values, and comments placed after a secret on the same line.

Use a secret manager as the authoritative backup. The deployment file is an input, not an adequate recovery system.

Configure identity and stable keys

Agent Barn requires three stable cryptographic values and one bootstrap administrator credential.

Generate the stable values

Generate the signing key:

Signing key
openssl rand -hex 32

Generate the Fernet encryption key:

Encryption key
python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"

Generate the LiteLLM master key:

LiteLLM master key
echo "sk-$(openssl rand -hex 24)"

Add them to the configuration:

Stable keys
SECRET_SIGNING_KEY=REPLACE_WITH_GENERATED_SIGNING_KEY
AGENT_TOKEN_ENCRYPTION_KEY=REPLACE_WITH_GENERATED_FERNET_KEY
LITELLM_MASTER_KEY=sk-REPLACE_WITH_GENERATED_VALUE

Stable-key responsibilities

Variable Requirement Used for Effect of an unplanned change
SECRET_SIGNING_KEY Stable Signing Agent Barn access tokens Existing signed sessions can become invalid
AGENT_TOKEN_ENCRYPTION_KEY Stable Encrypting Agent platform tokens, integration credentials, Shared Credentials, LiteLLM keys, Ingest keys, and stored OAuth tokens Existing encrypted data can no longer be decrypted
LITELLM_MASTER_KEY Stable LiteLLM administration, and encryption of its virtual-key data Existing Agent LiteLLM keys and LiteLLM database data can become unusable

Configure the bootstrap administrator

Bootstrap administrator
PLATFORM_ADMIN_CREDENTIALS=[email protected]:REPLACE_WITH_STRONG_PASSWORD

The password must contain at least eight characters, an uppercase letter, a lowercase letter, and a digit. Do not use a colon in the password, because the value uses a colon to separate the email from the password.

The bootstrap credential is used only when Agent Barn finds no existing Platform Administrator. Changing the environment variable after the initial bootstrap does not change the existing administrator’s password.

Set the environment label

Environment label
ENVIRONMENT=production

Use a distinct value such as staging for another stack. The label appears in operational metrics and alerts.

Configure data services

The Kubernetes deployment creates three independent PostgreSQL releases.

Database Purpose
Application PostgreSQL Users, Organizations, Agents, Templates, Skills, Activity, and product state
LiteLLM PostgreSQL LiteLLM virtual keys and spend data
Firecrawl PostgreSQL Self-hosted Firecrawl state

Configure each database independently:

Database credentials
POSTGRES_APP_USER=agentfarm
POSTGRES_APP_PASSWORD=REPLACE_WITH_UNIQUE_PASSWORD
POSTGRES_APP_DB=agentfarm

POSTGRES_LITELLM_USER=litellm
POSTGRES_LITELLM_PASSWORD=REPLACE_WITH_DIFFERENT_PASSWORD
POSTGRES_LITELLM_DB=litellm

POSTGRES_FIRECRAWL_USER=firecrawl
POSTGRES_FIRECRAWL_PASSWORD=REPLACE_WITH_ANOTHER_PASSWORD
POSTGRES_FIRECRAWL_DB=firecrawl

Generate URL-safe passwords with:

Password
openssl rand -hex 24

Hex values avoid connection-string escaping problems. Do not reuse one password across all three databases.

Local database URL

Native host commands require an explicit application database URL:

Local database URL
DB_CONNECTION_URL=postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@localhost:${POSTGRES_PORT}/${POSTGRES_DB}

Compose overrides this with the internal db service hostname, and Kubernetes derives the application connection URL from its POSTGRES_APP_* values.

Redis

Redis carries the general background worker and the Event Delivery pipeline:

Redis URL
REDIS_URL=redis://localhost:6379/0

Local Compose replaces the hostname with redis. Kubernetes uses:

In-cluster Redis
redis://redis:6379/0

Redis unavailability does not prevent the Product API from committing supported Domain Events, but low-latency Event Delivery processing stops until the worker and transport recover.

Firecrawl

Generate a platform Firecrawl key with openssl rand -hex 24, then configure it for Kubernetes:

Firecrawl key
FIRECRAWL_API_KEY=REPLACE_WITH_GENERATED_VALUE

The current deployment uses the same platform key for the self-hosted Firecrawl service and the default Agent integration. Individual Agents can later receive their own credential overrides — see Connect Firecrawl.

Configure models and Agent runtimes

Agent Barn sends model requests through LiteLLM, which uses OpenRouter as the configured provider.

Model request path
Agent runtime


LiteLLM proxy


OpenRouter

OpenRouter

Set a real OpenRouter inference key:

Provider key
OPENROUTER_API_KEY=sk-or-REPLACE_WITH_PROVIDER_KEY

OPENROUTER_API_KEY and LITELLM_MASTER_KEY are different credentials:

Variable Authority
OPENROUTER_API_KEY Makes provider model requests
LITELLM_MASTER_KEY Administers the self-hosted LiteLLM proxy and its virtual keys

Default model

Configure the default using the full Agent Barn model path:

Default model
AGENT_DEFAULT_MODEL=litellm/openrouter/z-ai/glm-5.2

The segment following litellm/openrouter/ must be a valid OpenRouter model ID.

Model catalogue allowlist

Limit the model picker with comma-separated fnmatch globs:

Allowlist
AGENT_MODEL_ALLOWLIST=z-ai/glm-5.2,openai/gpt-5*

Patterns match OpenRouter model IDs without the litellm/openrouter/ prefix. An empty value exposes the full available catalogue:

Unrestricted catalogue
AGENT_MODEL_ALLOWLIST=

An Organization can narrow its own allowed models further. The environment allowlist controls what the platform catalogue offers; it does not replace Organization model governance.

Runtime images

Kubernetes deployments use four compatible images:

Image tags
API_IMAGE_TAG=RELEASE_API_TAG
UI_IMAGE_TAG=RELEASE_UI_TAG
OPENCLAW_IMAGE_TAG=RELEASE_OPENCLAW_TAG
HERMES_IMAGE_TAG=RELEASE_HERMES_TAG

Local development uses full Agent image references:

Local Agent images
OPENCLAW_IMAGE=registry.example.com/agentbarn-openclaw-base:RELEASE_TAG
HERMES_IMAGE=registry.example.com/agentbarn-hermes-base:RELEASE_TAG

Kubernetes Agent workloads use OPENCLAW_IMAGE and HERMES_IMAGE. The older AGENT_IMAGE setting is not used by the current API.

Use the runtime image versions supplied with the selected Agent Barn release. Hermes and OpenClaw versions must stay compatible with that release — do not combine an arbitrary API image with unrelated runtime versions.

LiteLLM addresses

In Kubernetes, both the API and the Agents use the in-cluster service:

In-cluster LiteLLM
http://litellm:4000

In local k3d, the API container reaches LiteLLM through the Compose network, while Agent pods reach the host-published proxy through host.docker.internal on default port 7070:

Local Agent-facing LiteLLM
AGENT_LITELLM_BASE_URL=http://host.docker.internal:7070

Running Agents keep their current pod image and generated configuration until they are stopped and started again.

Configure URLs, DNS, and TLS

A Kubernetes deployment uses separate UI, API, and Grafana hostnames:

Hostnames
UI_HOST=agentbarn.example.com
API_HOST=api.agentbarn.example.com
GRAFANA_HOST=grafana.agentbarn.example.com
WEB_APP_URL=https://agentbarn.example.com

Use hostnames without a scheme for UI_HOST, API_HOST, and GRAFANA_HOST, and the complete public origin for WEB_APP_URL. The API chart derives its external URL from the first configured API hostname.

DNS

Point all three hostnames at the public address of the Traefik ingress controller, then verify resolution before deploying:

Resolve hostnames
dig +short agentbarn.example.com
dig +short api.agentbarn.example.com
dig +short grafana.agentbarn.example.com

Ingress exposure

The UI ingress exposes /. The API ingress exposes only:

API ingress path
/api

The API ingress deliberately does not expose /metrics, the Ingest API port, or internal worker endpoints. Prometheus scrapes metrics through Kubernetes Services, and Agent runtimes send telemetry to the in-cluster Ingest service rather than a public ingress.

TLS

The API and UI charts currently use this cert-manager ClusterIssuer:

ClusterIssuer
letsencrypt-http01

Confirm that it exists:

Check the issuer
kubectl get clusterissuer letsencrypt-http01

HTTP-01 requires publicly reachable DNS and ingress. A private installation needs a certificate strategy compatible with its network.

Configure Kubernetes access and storage

Deployment kubeconfig

Set the kubeconfig used by kubectl, Helm, and Helmfile, using an absolute path:

Deployment kubeconfig
KUBECONFIG=/absolute/path/to/agent-barn-production.yaml

Namespace

Production uses:

Production namespace
NAMESPACE=agent-farm

Staging uses:

Staging namespace
NAMESPACE=agent-farm-staging

The API chart sets K8S_NAMESPACE from the Helm release namespace, which prevents a staging API from creating Agent workloads in production.

API-facing kubeconfig

The Agent Barn API needs Kubernetes access to manage Agent resources. When POD_KUBECONFIG_B64 is omitted, deploy.sh base64-encodes the deployment kubeconfig:

API kubeconfig
POD_KUBECONFIG_B64=

For production, supply a dedicated namespace-scoped kubeconfig instead of reusing a cluster-administrator identity. That identity needs to manage Deployments, Services, ConfigMaps, Secrets, PersistentVolumeClaims, Pods, Pod logs, and the exec and port-forward operations the health and log workflows use.

Container registry

Registry and repositories
REGISTRY_PREFIX=registry.example.com/agent-barn
REGISTRY_SERVER=registry.example.com
REGISTRY_USERNAME=REPLACE_WITH_USERNAME
REGISTRY_PASSWORD=REPLACE_WITH_ACCESS_TOKEN

API_IMAGE_REPOSITORY=api
UI_IMAGE_REPOSITORY=ui
HERMES_IMAGE_REPOSITORY=hermes-base
OPENCLAW_IMAGE_REPOSITORY=openclaw-base

REGISTRY_PREFIX is prepended to image repository names, and REGISTRY_SERVER identifies the registry for authentication.

Storage

Select a StorageClass, or leave it empty to use the cluster default:

StorageClass
STORAGE_CLASS=REPLACE_WITH_STORAGE_CLASS

The StorageClass is used by the application, LiteLLM, and Firecrawl PostgreSQL releases, by Prometheus, and by generated Agent PVCs. Use network-replicated storage when node-loss durability is required.

Configure optional integrations

Transactional email

Agent Barn uses Cloudflare Email Sending for invitations, password recovery, and Agent lifecycle notifications. Email is enabled only when all three values are set:

Email configuration
CLOUDFLARE_ACCOUNT_ID=REPLACE_WITH_ACCOUNT_ID
CLOUDFLARE_API_TOKEN=REPLACE_WITH_EMAIL_SENDING_TOKEN
SENDER_EMAIL=[email protected]

The Cloudflare token needs Email Sending: Edit permission, and the SENDER_EMAIL domain must be verified for Email Sending. Use a separate mail.-style subdomain per environment:

Sender domains

To disable delivery, leave all three empty:

Email disabled
CLOUDFLARE_ACCOUNT_ID=
CLOUDFLARE_API_TOKEN=
SENDER_EMAIL=

With delivery disabled, send attempts are logged and treated as no-ops. Avoid configuring only one or two values, because the platform still considers email disabled.

Google Workspace OAuth

Create a Google OAuth 2.0 Web application client and register this redirect URI:

Callback URI
https://agentbarn.example.com/api/v1/integrations/google/callback

Then configure the client values:

Google OAuth client
GOOGLE_CLOUD_CLIENT_ID=REPLACE_WITH_CLIENT_ID
GOOGLE_CLOUD_CLIENT_SECRET=REPLACE_WITH_CLIENT_SECRET

Google OAuth is enabled only when both values are set and the callback matches <WEB_APP_URL>/api/v1/integrations/google/callback exactly. Leave both empty to disable it.

These are application-owned OAuth client credentials. The refresh token created when a user connects Google Workspace remains Agent-specific and encrypted by Agent Barn — see Connect Google Workspace.

Configure workers and Telemetry

Event Delivery worker

The Kubernetes API chart deploys a general Dramatiq worker and a scheduled Event Delivery reconciliation CronJob. Both use Redis. The default reconciliation schedule is:

Reconciliation schedule
*/5 * * * *

Local development uses:

Local worker
make redis-up
make dev-worker

A one-shot local reconciliation pass is available through:

Reconcile once
make reconcile

Ingest API

Agent runtimes push Conversations and Tool Calls to the Ingest API. It runs from the API image as a separate FastAPI application, listens on port 8001, and authenticates each Agent with a per-start Ingest key.

The default Kubernetes address is:

In-cluster Ingest
http://agentbarn-api:8001/ingest/v1

Local Agent pods use:

Local Ingest
http://host.docker.internal:8001/ingest/v1

A broken Ingest path does not necessarily stop an Agent from replying. Instead, Activity can stay empty even though the Agent is working. Make sure Agent pods can reach both services in Kubernetes:

Agent reachability
LiteLLM: http://litellm:4000
Ingest:  http://agentbarn-api:8001/ingest/v1

Configure monitoring

The current Helmfile deploys Prometheus, Grafana, Alertmanager, kube-state-metrics, and the Agent Barn dashboards and alert rules.

Add the following variables to .env.deploy:

Monitoring configuration
SLACK_ALERTS_WEBHOOK_URL=REPLACE_WITH_ALERT_WEBHOOK
GRAFANA_ADMIN_PASSWORD=REPLACE_WITH_STRONG_PASSWORD
GRAFANA_HOST=grafana.agentbarn.example.com

Build the chart dependencies before deployment:

Chart dependencies
helm dependency build helm/monitoring

The monitoring stack is namespace-scoped and does not create its own cluster-scoped RBAC.

Prometheus reads Product API metrics, Ingest API metrics, LiteLLM metrics, Agent health metrics, Kubernetes state for the release namespace, and the remaining OpenRouter credits when the provider key has a configured credit limit.

Grafana is the only monitoring component exposed through ingress. Use a dedicated Slack webhook, and restrict access to the Grafana administrator password.

Separate production and staging

Use separate configuration and infrastructure identities for every environment.

Setting Production Staging
Namespace agent-farm agent-farm-staging
Environment label production staging
UI hostname Production hostname Staging hostname
API hostname Production hostname Staging hostname
Grafana hostname Production hostname Staging hostname
Sender domain mail. subdomain Separate mail-staging. subdomain
Image tags Production release tags Compatible staging tags
Databases and PVCs Production namespace Staging namespace
Platform stable keys Production values Separate staging values
Kubeconfig Production-scoped Staging-scoped

Do not reuse the production signing key, encryption key, database passwords, or LiteLLM master key in staging.

The OpenRouter inference key and the Cloudflare account can technically be shared, but doing so shares provider quota and failure impact. Use independent credentials when operational isolation matters.

To use an environment-specific file:

Deploy staging
ENV_FILE=.env.deploy.staging ./deploy.sh

Configuration variable reference

Required Kubernetes deployment inputs

Group Requirement Variables
Cluster Required KUBECONFIG, NAMESPACE
Registry Required REGISTRY_PREFIX, REGISTRY_SERVER, REGISTRY_USERNAME, REGISTRY_PASSWORD
Images Required API_IMAGE_REPOSITORY, UI_IMAGE_REPOSITORY, HERMES_IMAGE_REPOSITORY, OPENCLAW_IMAGE_REPOSITORY, and all four image tags
Application database Required POSTGRES_APP_USER, POSTGRES_APP_PASSWORD, POSTGRES_APP_DB
LiteLLM database Required POSTGRES_LITELLM_USER, POSTGRES_LITELLM_PASSWORD, POSTGRES_LITELLM_DB
Firecrawl database Required POSTGRES_FIRECRAWL_USER, POSTGRES_FIRECRAWL_PASSWORD, POSTGRES_FIRECRAWL_DB
Models Required LITELLM_MASTER_KEY, OPENROUTER_API_KEY
Application identity Required SECRET_SIGNING_KEY, AGENT_TOKEN_ENCRYPTION_KEY, PLATFORM_ADMIN_CREDENTIALS, ENVIRONMENT
URLs Required UI_HOST, API_HOST, WEB_APP_URL, GRAFANA_HOST
Firecrawl Required FIRECRAWL_API_KEY
Monitoring Required SLACK_ALERTS_WEBHOOK_URL, GRAFANA_ADMIN_PASSWORD, GRAFANA_HOST

Conditional and optional inputs

Variable Requirement Purpose
POD_KUBECONFIG_B64 Optional Recommended for production A dedicated, namespace-scoped Kubernetes identity for the API
STORAGE_CLASS Conditional When the cluster default is unsuitable Select non-default persistent storage
AGENT_DEFAULT_MODEL Optional Override the built-in default model
AGENT_MODEL_ALLOWLIST Optional Narrow the platform model catalogue
CLOUDFLARE_ACCOUNT_ID Conditional Required with the other two email values Enable transactional email
CLOUDFLARE_API_TOKEN Conditional Required with the other two email values Cloudflare Email Sending authorization
SENDER_EMAIL Conditional Required with the other two email values The verified From address
GOOGLE_CLOUD_CLIENT_ID Conditional Required with the client secret Enable Google Workspace OAuth
GOOGLE_CLOUD_CLIENT_SECRET Conditional Required with the client ID The Google OAuth client secret
FIRECRAWL_BULL_AUTH_KEY Optional Protect the internal Firecrawl BullMQ administration interface
INGRESS_CLUSTER_ISSUER Optional Currently ineffective Present in the template, but not wired into the API or UI chart by Helmfile

Generated values

Value Requirement Generated by
Application database URL Generated Helmfile, from the POSTGRES_APP_* values
LiteLLM database URL Generated Helmfile, from the POSTGRES_LITELLM_* values
API external URL Generated Helmfile, from the first API_HOST
API pod kubeconfig Generated deploy.sh, from KUBECONFIG unless POD_KUBECONFIG_B64 is supplied
Agent Barn LiteLLM API key Generated The API chart pre-install and pre-upgrade hook
Per-Agent LiteLLM keys Generated The Agent creation workflow
Per-start Ingest key Generated The Agent start workflow
Registry pull Secret Generated The API chart
TLS Secrets Generated cert-manager

Do not manually create the generated per-Agent keys.

Apply configuration changes

Local changes require restarting the affected processes or containers:

Restart locally
./stop.sh
./run.sh --detach

Kubernetes changes require another deployment:

Redeploy
./deploy.sh

The API chart hashes Secret content into its pod template, so Secret changes roll the API and worker pods.

Changes that can require an Agent restart include runtime image changes, LiteLLM or Ingest addresses, generated platform policy, credential materialization, and Template or Skill changes applied to the Agent.

Validate the configuration

Before deployment, verify the Kubernetes context:

Context
kubectl config current-context
kubectl cluster-info

Confirm storage:

Storage
kubectl get storageclass

Confirm the ingress and certificate prerequisites:

Ingress and issuer
kubectl get ingressclass traefik
kubectl get clusterissuer letsencrypt-http01

Confirm namespace permissions:

Permissions
kubectl auth can-i create deployments --namespace agent-farm
kubectl auth can-i create services --namespace agent-farm
kubectl auth can-i create secrets --namespace agent-farm
kubectl auth can-i create persistentvolumeclaims --namespace agent-farm

Confirm that DNS resolves:

DNS
dig +short agentbarn.example.com
dig +short api.agentbarn.example.com
dig +short grafana.agentbarn.example.com

Confirm the monitoring chart is prepared:

Chart dependencies
helm dependency build helm/monitoring

Review the deployment file without printing its secret values:

List variable names
grep -E '^[A-Z0-9_]+=' .env.deploy | cut -d= -f1 | sort

After deployment, verify the release:

Release state
helm list --namespace agent-farm
kubectl get deployments,statefulsets,pods --namespace agent-farm
kubectl get pvc,ingress,certificate --namespace agent-farm

Verify the API:

Health check
curl --fail https://api.agentbarn.example.com/api/v1/health

A healthy response resembles:

Response
{
  "status": "ok",
  "db": "connected"
}

Security and rotation

Apply these rules to the configuration:

  • Never commit .env or .env.deploy
  • Store the stable keys in an encrypted secret manager with tested recovery access
  • Use a namespace-scoped kubeconfig for the API
  • Use registry access tokens instead of personal passwords
  • Give Cloudflare tokens only the required Email Sending permission
  • Use unique passwords for each of the three databases
  • Keep secrets out of ENVIRONMENT, hostnames, model allowlists, and other visible values
  • Do not render Helm Secrets into shared CI logs
  • Restrict access to deployment artifacts and backups
  • Back up PostgreSQL and the stable keys together
  • Test recovery using the restored keys and database data
  • Rotate provider and registry tokens independently from the stable encryption keys
  • Treat stable-key rotation as a migration with rollback and verification steps

A database backup without AGENT_TOKEN_ENCRYPTION_KEY cannot recover encrypted credentials. A LiteLLM database backup without its original LITELLM_MASTER_KEY can leave its virtual-key data unusable.

Current configuration constraints

Account for these current limitations:

  1. .env.deploy.spec does not list SLACK_ALERTS_WEBHOOK_URL, GRAFANA_ADMIN_PASSWORD, or GRAFANA_HOST, but Helmfile requires them.
  2. INGRESS_CLUSTER_ISSUER is present in .env.deploy.spec but is not passed into the API or UI chart.
  3. deploy.sh does not build the monitoring chart dependency.
  4. deploy.sh applies the production k8s/agent-farm-user.yaml bootstrap manifest regardless of a changed NAMESPACE.
  5. The API-facing kubeconfig defaults to the deployment kubeconfig, which may be more privileged than the API requires.
  6. The deployment uses in-cluster LiteLLM, Ingest, Firecrawl, and Redis addresses that are not all exposed as .env.deploy overrides.
  7. Some api/core/config.py settings are not wired through the Helm deployment and are not supported .env.deploy inputs.
  8. The namespace and associated ServiceAccount names intentionally retain agent-farm naming after the product and repository rebrand.

Troubleshooting

Symptom Likely cause Resolution
run.sh reports missing variables A required local value is blank Fill the named values in .env and run the launcher again.
API startup fails while initializing data The bootstrap password does not satisfy the policy Use at least eight characters with an uppercase letter, a lowercase letter, and a digit.
Changing PLATFORM_ADMIN_CREDENTIALS does not change the login The bootstrap administrator already exists Change the password through the supported account workflow instead.
Existing credentials can no longer be decrypted AGENT_TOKEN_ENCRYPTION_KEY changed Restore the original key, or perform a planned credential migration.
Existing Agent model keys stop working LITELLM_MASTER_KEY or the LiteLLM database changed Restore the original master key together with the LiteLLM database.
An Agent starts but never answers LiteLLM is unreachable, or the OpenRouter key is invalid Verify the Agent-facing LiteLLM address, proxy health, and the provider key.
An Agent answers but its Activity stays empty The Agent cannot reach the Ingest API Verify the Ingest base URL, port 8001, DNS, and any NetworkPolicy.
An Agent pod uses the wrong image Image tags are incompatible or stale Configure the release’s matching runtime tags, then stop and start the Agent.
Kubernetes reports ImagePullBackOff The registry credentials, prefix, repository, or tag is wrong Inspect the pod events and the generated pull Secret.
PersistentVolumeClaims remain Pending STORAGE_CLASS is missing or incompatible Select a dynamically provisioned ReadWriteOnce StorageClass.
PostgreSQL rejects its configured password after an edit The Kubernetes Secret changed but the initialized database user did not Perform a coordinated database credential rotation.
Email sends are logged but never delivered One or more of the three email values is missing Set all three Cloudflare values and verify the sender domain.
Cloudflare rejects the email request The token lacks permission, or the sender domain is unverified Grant Email Sending permission and complete domain verification.
Google OAuth reports a redirect mismatch The registered URI does not exactly match the WEB_APP_URL origin Register the exact callback URI and deploy again.
Event Deliveries remain Pending Redis, the worker, or reconciliation is unavailable Check Redis, the worker Deployment, and the reconciliation CronJob.
Certificates remain not ready DNS, ingress, or the ClusterIssuer is incorrect Inspect the Ingress, Certificate, Challenge, and ClusterIssuer resources.
Changing INGRESS_CLUSTER_ISSUER has no effect The variable is not wired into the charts Use the currently supported issuer, or update the deployment wiring.
Staging Agents appear in the production namespace The namespace or API kubeconfig wiring is wrong Verify the release namespace, K8S_NAMESPACE, and the staging bootstrap manifest.
Platform changes apply but running Agents are unchanged Agent workloads keep the configuration generated at their last start Stop and start the affected Agents.

Next steps

  1. Confirm every required value is present and every stable key is backed up.
  2. Validate the cluster, storage, ingress, and DNS prerequisites.
  3. Apply the configuration to a cluster.
  4. Verify the API health endpoint and the generated Agent workloads.
  5. Continue to Deploy Agent Barn to Kubernetes.
Documentation