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:
- Environment file A local, secret-bearing .env for Docker and k3d, or .env.deploy for Kubernetes. Neither file is committed.
- Deployment tooling run.sh and compose.yml locally, or deploy.sh and helmfile.yaml.gotmpl for Kubernetes.
- 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.
- Platform services The Agent Barn API, UI, PostgreSQL releases, LiteLLM, Redis, Firecrawl, workers, and monitoring.
- 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-barnrepository - 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:
cp .env.spec .envOpen .env and replace the placeholder values. The full local launcher checks its required values before it creates the cluster or starts containers:
./run.shIf a required value is missing, the script exits and lists the missing variable names.
Kubernetes environment
From the deployment directory:
cp .env.deploy.spec .env.deployRestrict access to the file:
chmod 600 .env.deployThe file is sourced by a shell, so use plain assignments:
KEY=valueAvoid 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:
openssl rand -hex 32Generate the Fernet encryption key:
python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"Generate the LiteLLM master key:
echo "sk-$(openssl rand -hex 24)"Add them to the configuration:
SECRET_SIGNING_KEY=REPLACE_WITH_GENERATED_SIGNING_KEY
AGENT_TOKEN_ENCRYPTION_KEY=REPLACE_WITH_GENERATED_FERNET_KEY
LITELLM_MASTER_KEY=sk-REPLACE_WITH_GENERATED_VALUEStable-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
PLATFORM_ADMIN_CREDENTIALS=[email protected]:REPLACE_WITH_STRONG_PASSWORDThe 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=productionUse 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:
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=firecrawlGenerate URL-safe passwords with:
openssl rand -hex 24Hex 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:
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://localhost:6379/0Local Compose replaces the hostname with redis. Kubernetes uses:
redis://redis:6379/0Redis 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_API_KEY=REPLACE_WITH_GENERATED_VALUEThe 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.
Agent runtime
│
▼
LiteLLM proxy
│
▼
OpenRouterOpenRouter
Set a real OpenRouter inference key:
OPENROUTER_API_KEY=sk-or-REPLACE_WITH_PROVIDER_KEYOPENROUTER_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:
AGENT_DEFAULT_MODEL=litellm/openrouter/z-ai/glm-5.2The segment following litellm/openrouter/ must be a valid OpenRouter model ID.
Model catalogue allowlist
Limit the model picker with comma-separated fnmatch globs:
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:
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:
API_IMAGE_TAG=RELEASE_API_TAG
UI_IMAGE_TAG=RELEASE_UI_TAG
OPENCLAW_IMAGE_TAG=RELEASE_OPENCLAW_TAG
HERMES_IMAGE_TAG=RELEASE_HERMES_TAGLocal development uses full Agent image references:
OPENCLAW_IMAGE=registry.example.com/agentbarn-openclaw-base:RELEASE_TAG
HERMES_IMAGE=registry.example.com/agentbarn-hermes-base:RELEASE_TAGKubernetes 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:
http://litellm:4000In 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:
AGENT_LITELLM_BASE_URL=http://host.docker.internal:7070Running 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:
UI_HOST=agentbarn.example.com
API_HOST=api.agentbarn.example.com
GRAFANA_HOST=grafana.agentbarn.example.com
WEB_APP_URL=https://agentbarn.example.comUse 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:
dig +short agentbarn.example.com
dig +short api.agentbarn.example.com
dig +short grafana.agentbarn.example.comIngress exposure
The UI ingress exposes /. The API ingress exposes only:
/apiThe 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:
letsencrypt-http01Confirm that it exists:
kubectl get clusterissuer letsencrypt-http01HTTP-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:
KUBECONFIG=/absolute/path/to/agent-barn-production.yamlNamespace
Production uses:
NAMESPACE=agent-farmStaging uses:
NAMESPACE=agent-farm-stagingThe 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:
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_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-baseREGISTRY_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:
STORAGE_CLASS=REPLACE_WITH_STORAGE_CLASSThe 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:
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:
Production: [email protected]
Staging: [email protected]To disable delivery, leave all three empty:
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:
https://agentbarn.example.com/api/v1/integrations/google/callbackThen configure the client values:
GOOGLE_CLOUD_CLIENT_ID=REPLACE_WITH_CLIENT_ID
GOOGLE_CLOUD_CLIENT_SECRET=REPLACE_WITH_CLIENT_SECRETGoogle 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:
*/5 * * * *Local development uses:
make redis-up
make dev-workerA one-shot local reconciliation pass is available through:
make reconcileIngest 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:
http://agentbarn-api:8001/ingest/v1Local Agent pods use:
http://host.docker.internal:8001/ingest/v1A 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:
LiteLLM: http://litellm:4000
Ingest: http://agentbarn-api:8001/ingest/v1Configure 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:
SLACK_ALERTS_WEBHOOK_URL=REPLACE_WITH_ALERT_WEBHOOK
GRAFANA_ADMIN_PASSWORD=REPLACE_WITH_STRONG_PASSWORD
GRAFANA_HOST=grafana.agentbarn.example.comBuild the chart dependencies before deployment:
helm dependency build helm/monitoringThe 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:
ENV_FILE=.env.deploy.staging ./deploy.shConfiguration 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:
./stop.sh
./run.sh --detachKubernetes changes require another deployment:
./deploy.shThe 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:
kubectl config current-context
kubectl cluster-infoConfirm storage:
kubectl get storageclassConfirm the ingress and certificate prerequisites:
kubectl get ingressclass traefik
kubectl get clusterissuer letsencrypt-http01Confirm namespace 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-farmConfirm that DNS resolves:
dig +short agentbarn.example.com
dig +short api.agentbarn.example.com
dig +short grafana.agentbarn.example.comConfirm the monitoring chart is prepared:
helm dependency build helm/monitoringReview the deployment file without printing its secret values:
grep -E '^[A-Z0-9_]+=' .env.deploy | cut -d= -f1 | sortAfter deployment, verify the release:
helm list --namespace agent-farm
kubectl get deployments,statefulsets,pods --namespace agent-farm
kubectl get pvc,ingress,certificate --namespace agent-farmVerify the API:
curl --fail https://api.agentbarn.example.com/api/v1/healthA healthy response resembles:
{
"status": "ok",
"db": "connected"
}Security and rotation
Apply these rules to the configuration:
- Never commit
.envor.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:
- .env.deploy.spec does not list SLACK_ALERTS_WEBHOOK_URL, GRAFANA_ADMIN_PASSWORD, or GRAFANA_HOST, but Helmfile requires them.
- INGRESS_CLUSTER_ISSUER is present in .env.deploy.spec but is not passed into the API or UI chart.
- deploy.sh does not build the monitoring chart dependency.
- deploy.sh applies the production k8s/agent-farm-user.yaml bootstrap manifest regardless of a changed NAMESPACE.
- The API-facing kubeconfig defaults to the deployment kubeconfig, which may be more privileged than the API requires.
- The deployment uses in-cluster LiteLLM, Ingest, Firecrawl, and Redis addresses that are not all exposed as .env.deploy overrides.
- Some api/core/config.py settings are not wired through the Helm deployment and are not supported .env.deploy inputs.
- 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
- Confirm every required value is present and every stable key is backed up.
- Validate the cluster, storage, ingress, and DNS prerequisites.
- Apply the configuration to a cluster.
- Verify the API health endpoint and the generated Agent workloads.
- Continue to Deploy Agent Barn to Kubernetes.