Agent deployment platform on Kubernetes. Deploy, manage, and monitor AI agents at scale.
Live demo: ranch.cleanslice.org
Built with CleanSlice architecture.
Install the CLI globally β it auto-clones the project on first run:
bun add -g @cleanslice/ranch
# or: npm install -g @cleanslice/ranch
ranch dev # offers to clone if no checkout, then starts api + app + admin + local k3dSee cli/README.md for all ranch commands.
git clone https://github.com/CleanSlice/ranch.git
cd ranch
make initThe setup wizard will guide you through:
- Installing dependencies (Bun, Docker)
- Setting up local PostgreSQL and running migrations
- Optionally: configuring and deploying to Hetzner Cloud
After setup, start developing:
make dev # Starts api:3000 + app:3001 + admin:3002βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Hetzner Cloud β
β β
β ββββββββββββββ ββββββββββββββββββ βββββββββββββββββ β
β β ArgoCD β β Argo Workflows β β CloudNativePGβ β
β β (GitOps) β β (Agent runs) β β (PostgreSQL) β β
β βββββββ¬βββββββ ββββββββ²ββββββββββ βββββββββββββββββ β
β β sync β submit β
β βΌ β β
β ββββββββββββββββββββββββ΄βββββββββββββββββββββββββββ β
β β Agent Manager (api) β β
β β NestJS + Prisma + CleanSlice β β
β βββββββββββββββββββββββββββββββββββββββββββββββββββ β
β βββββββββββββββββββ βββββββββββββββββββββββββββββββ β
β β Dashboard (app)β β Admin Panel (admin) β β
β β Nuxt + Vue 3 β β Nuxt + Vue 3 β β
β βββββββββββββββββββ βββββββββββββββββββββββββββββββ β
β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β Agent Pods (dynamic, via Argo Workflows) β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
| Layer | Technology |
|---|---|
| Backend | NestJS, Prisma, PostgreSQL |
| Frontend | Nuxt 3, Vue 3, Pinia, Tailwind, shadcn-vue |
| Infrastructure | Terraform, Hetzner Cloud, k3s |
| Deployment | ArgoCD (GitOps), Argo Workflows |
| Runtime | Bun |
| Monorepo | Turborepo |
ranch/
βββ api/ # NestJS backend
β βββ src/slices/
β βββ setup/ # prisma, init, health
β βββ user/ # auth + user
β βββ agent/ # agent, file, pod, secret, template, templateFile
β βββ workflow/ # Argo Workflows integration
β βββ bridle/ # chat (sessions, messages, streaming)
β βββ mcp/ # MCP runtime hosted at /mcp/*
β βββ mcpServer/ # MCP server registry
β βββ llm/ # LLM provider config
β βββ skill/ # Reusable agent skills
β βββ rancher/ # Per-tenant ranch (workspace) management
β βββ reins/ # Access control / API keys
β βββ setting/ # System settings
β βββ usage/ # Usage metering
β βββ log/ # Agent logs
β βββ aws/ # AWS-backed integrations (S3, etc.)
βββ app/ # Nuxt user dashboard
β βββ slices/ # setup, agent, bridle, template, user, common
βββ admin/ # Nuxt admin panel
β βββ slices/ # setup, agent, bridle, llm, mcpServer, rancher,
β # reins, setting, skill, usage, user, common
βββ cli/ # @cleanslice/ranch β published to npm
βββ rancher/ # Default agent template ("rancher" agent)
βββ terraform/ # Hetzner infrastructure
β βββ modules/ # cluster, network, bootstrap, dns, database, storage, apps
β βββ environments/ # dev, prod, dreamvention (+ your custom env)
βββ k8s/ # Kubernetes manifests
β βββ argocd/ # App-of-apps
β βββ infrastructure/ # Argo Workflows, CNPG, database
β βββ platform/ # api, app, admin deployments
β βββ templates/ # Argo WorkflowTemplate + RBAC for agents
β βββ local/ # Local k3d-only manifests (CoreDNS host alias, etc.)
β βββ deploy/ # Deploy hooks
βββ .github/workflows/ # CI/CD
- Bun β
curl -fsSL https://bun.sh/install | bash - Docker β for local PostgreSQL
- Terraform β for infrastructure
- kubectl β for cluster management
- Helm β for chart management
The ranch CLI wraps the most-used make targets and works from any
directory once installed globally. See cli/README.md
for the full reference.
bun add -g @cleanslice/ranch # one-time install
ranch dev # start api + app + admin
ranch dev api # or just one service: api | app | admin
ranch down # stop dev servers, postgres, k3d
ranch db start | stop | reset | studio
ranch generate # regenerate Prisma schema from slices
ranch status # show what's running locally
ranch where # show which Ranch checkout the CLI is usingEquivalent targets, run from the project root:
make help # Show all commands
# Development
make setup # Full local setup (first time)
make dev # Start all services (api:3000, app:3001, admin:3002)
make dev-api # Start API only
make dev-app # Start app only
make dev-admin # Start admin only
# Database
make db # Start PostgreSQL via Docker
make db-stop # Stop PostgreSQL
make db-reset # Reset database (destroy data)
make migrate # Generate schema + run migrations
make generate # Regenerate schema.prisma from slices
make studio # Open Prisma Studio
# Build & Test
make build # Build all services
make lint # Lint all services
make test # Run tests
make clean # Remove node_modules and build artifactsAfter ranch dev (or make dev):
| URL | Description |
|---|---|
http://localhost:3000 |
API (NestJS) |
http://localhost:3000/api |
Swagger UI β full endpoint reference |
http://localhost:3000/mcp/* |
MCP runtime (tools exposed via @Tool decorators) |
http://localhost:3000/health |
Health check |
http://localhost:3001 |
App (user dashboard) |
http://localhost:3002 |
Admin panel |
ranch dev also brings up a local k3d cluster (ranch) with the
platform and agents namespaces and Argo workflow templates pre-applied,
so the API can submit real agent workflows against a local Kubernetes.
Kubeconfig is written to ~/.kube/ranch-local.yaml.
For RAG-backed agents, a LightRAG + Ollama + Postgres stack ships behind a Docker Compose profile:
make lightrag-up # First run pulls ~3GB of models β LightRAG at :9621
make lightrag-down # Stop (keeps data)
make lightrag-reset # Wipe data + models
make lightrag-logs # Tail container logsEach slice defines its own .prisma file at the slice root. They are merged into prisma/schema.prisma by prisma-import at build time.
api/src/slices/
βββ setup/prisma/prisma.prisma # datasource + generator
βββ agent/agent/agent.prisma # Agent model
βββ agent/template/template.prisma # Template model
βββ user/user/user.prisma # User model
Edit the slice .prisma files, then:
make generate # Merge into prisma/schema.prisma
make migrate # Create migration + generate clientπ Full Terraform guide (remote state backend, environments, imports, DNS, gotchas):
terraform/README.md
# Copy the dev template
cp -r terraform/environments/dev terraform/environments/myenv
# Edit variables
vi terraform/environments/myenv/terraform.tfvars.example
# Copy and fill in your values:
cp terraform/environments/myenv/terraform.tfvars.example terraform/environments/myenv/terraform.tfvarsRequired variables in terraform.tfvars:
hcloud_token = "your-hetzner-api-token"
domain = "ranch.yourdomain.com"
admin_ip = "YOUR_IP/32" # curl ifconfig.me
ssh_public_key_path = "~/.ssh/id_ed25519.pub"The k3s cluster requires MicroOS snapshots on Hetzner:
brew install packer # if not installed
# Download and build snapshots
cd /tmp
curl -sLO https://raw.githubusercontent.com/kube-hetzner/terraform-hcloud-kube-hetzner/master/packer-template/hcloud-microos-snapshots.pkr.hcl
packer init hcloud-microos-snapshots.pkr.hcl
HCLOUD_TOKEN="your-token" packer build hcloud-microos-snapshots.pkr.hclmake infra-init ENV=myenv # Download providers
make infra-plan ENV=myenv # Preview changes
make infra-apply ENV=myenv # Create cluster (~5-10 min)This creates:
- k3s cluster with Traefik ingress and cert-manager
- VPC + Firewall
- Load Balancer
make kubeconfig ENV=myenv
export KUBECONFIG=~/.kube/ranch-myenv
kubectl get nodes# Add Helm repos
helm repo add argo https://argoproj.github.io/argo-helm
helm repo add cnpg https://cloudnative-pg.github.io/charts
helm repo update
# Install ArgoCD
helm install argocd argo/argo-cd \
--namespace argocd --create-namespace \
--set server.ingress.enabled=true \
--set server.ingress.ingressClassName=traefik \
--set "server.ingress.hosts[0]=argocd.ranch.yourdomain.com"
# Install Argo Workflows
helm install argo-workflows argo/argo-workflows \
--namespace argo --create-namespace
# Install CloudNativePG
helm install cnpg cnpg/cloudnative-pg \
--namespace cnpg-system --create-namespace
# Create namespaces
kubectl create namespace platform
kubectl create namespace agentsRanch ships five public services behind one shared Hetzner Load Balancer. You need an A record per subdomain at your DNS provider β the records themselves are not managed by Terraform (intentional: keeps the DNS zone your single source of truth and lets you change provider without touching the platform module).
Required A records β point each at the same Load Balancer IP:
| Subdomain | Serves | Required? |
|---|---|---|
ranch.yourdomain.com |
App (root, end-user UI) | yes |
api.ranch.yourdomain.com |
NestJS API | yes |
admin.ranch.yourdomain.com |
Admin panel (Nuxt) | yes |
argocd.ranch.yourdomain.com |
ArgoCD UI | yes |
browser.ranch.yourdomain.com |
Browser-pool live VNC view | yes β agents send users this URL for manual logins (Instagram, Meta Ads, etc.). Without it, every site that needs an interactive login is unreachable. |
Get the Load Balancer IP after terraform apply:
kubectl get svc -n traefik traefik -o jsonpath='{.status.loadBalancer.ingress[0].ip}'
# or, equivalently, ask Terraform:
terraform -chdir=terraform/environments/<env> output dns_records_neededThe dns_records_needed output lists every subdomain that needs a record
and the IP to point it at β keep this in sync if you ever add a new
public-facing ingress (otherwise cert-manager will spin forever on a
challenge that can't resolve).
Propagation: 1β5 min typical (set TTL=300). cert-manager then
issues a Let's Encrypt cert automatically via the HTTP-01 challenge β
the first hit to https://<subdomain>/ after propagation triggers it.
Smoke test once propagated:
for sub in "" api. admin. argocd. browser.; do
host="${sub}ranch.yourdomain.com"
printf "%-45s " "$host"
curl -sS -o /dev/null -w "%{http_code}\n" "https://$host/" --max-time 5 || echo "(timeout)"
doneAll five should return a non-zero HTTP code (200/301/302/401 are all fine β means the cert handshake succeeded and Traefik routed the request).
# Get ArgoCD password
make argocd-password
# Login to ArgoCD UI at https://argocd.ranch.yourdomain.com
# Username: admin
# Password: <output from above>
# Deploy app-of-apps
make deploymake k8s-secrets # Interactive β will ask for DATABASE_URLRanch is designed to be forked per-organization:
# 1. Fork CleanSlice/ranch β YourOrg/ranch
# 2. Clone your fork
git clone git@github.com:YourOrg/ranch.git
cd ranch
# 3. Add upstream
git remote add upstream git@github.com:CleanSlice/ranch.git
# 4. Create your environment
cp -r terraform/environments/dev terraform/environments/yourenv
# 5. Customize k8s manifests
# - k8s/argocd/app-of-apps.yaml β change repoURL to YourOrg/ranch
# - k8s/platform/*/ingress.yaml β change hostnames
# - k8s/platform/*/deployment.yaml β change image registry
# - Makefile β change ENV default
# 6. Sync upstream changes
git fetch upstream
git merge upstream/main
git push origin mainmake k8s-status # Show nodes, pods, ArgoCD apps
make k8s-logs-api # Tail API logs
make argocd-password # Get ArgoCD admin password
make infra-destroy ENV=myenv # Tear down infrastructuregit push β GitHub Actions:
βββ CI (lint + test)
βββ Build Docker images β ghcr.io
βββ ArgoCD detects new image
βββ Syncs to cluster (zero-downtime rolling update)
ArgoCD manages:
- Infrastructure β Argo Workflows, CloudNativePG, PostgreSQL cluster
- Platform β API, App, Admin deployments
- Templates β Argo WorkflowTemplates for agent pods
Private β CleanSlice
