Skip to content

About

Full stack deployment of AEGIS from 100monkeys.ai

Resources

Stars

0 stars

Watchers

0 watching

Forks

 
 

Repository files navigation

aegis-deploy

Podman-based deployment for the AEGIS platform.

Prerequisites

  • Ubuntu 22.04/24.04 or Kali (Kali uses native Podman packages; make setup detects it)
  • Podman 4.0+ (rootless) -- make setup installs this on supported distros
  • GitHub PAT with read:packages (or gh auth) for pulling images from ghcr.io/100monkeys-ai
  • Optional local LLM: LM Studio on 0.0.0.0:1234 (infra comes up without a model)

Quick Start

git clone https://github.com/ar-fullsend/aegis-deploy.git
cd aegis-deploy
cp .env.example .env        # set AEGIS_ROOT, GHCR_*, POSTGRES_PASSWORD
make setup                   # install Podman + dependencies
make deploy                  # development profile (includes IAM)
make bootstrap-keycloak      # realm + clients (idempotent)
make generate-keys           # SEAL RSA keys
make status && make validate

OpenBao bootstrap runs automatically after the secrets pod. See docs/LOCAL-OPS.md for JWT, LM Studio, Grafana scrapes, and agent vs Temporal.

Deployment Profiles

Select a profile with PROFILE=<name> make deploy. Default: development.

Profile Pods Use Case
minimal secrets, core Local development with external DB
development database, secrets, temporal, seal-gateway, iam, core, mcp, storage, observability Full local dev (includes IAM + SeaweedFS + MCP)
full database, secrets, storage, temporal, seal-gateway, core, mcp, observability Complete platform storage path (no iam in profile)

edge is optional and not in any profile: make redeploy POD=edge.

Pod Architecture

Pod Services Ports
pod-core aegis-runtime + metrics-proxy 8088 (HTTP), 50051 (gRPC), 2049 (NFS), 9091 (loopback metrics), 9092 (Prometheus scrape)
pod-database PostgreSQL 15, postgres-exporter 5432, 9187
pod-secrets OpenBao 8200
pod-temporal Temporal 1.23 (auto-setup), Temporal UI 2.21, aegis-temporal-worker 7233 (gRPC), 8233 (UI)
pod-iam Keycloak 24 8180
pod-seal-gateway aegis-seal-gateway 8089 (HTTP), 50055 (gRPC)
pod-mcp zaru-mcp-server (aegis-mcp-tools) 8090 (MCP StreamableHTTP /mcp/v1)
pod-observability Jaeger 1.55, Prometheus 2.51, Grafana 10.4, Loki 3.0, Promtail 3.0, otelcol-contrib 0.99 16686 (Jaeger UI), 4317/4318 (OTLP → otelcol), 9090 (Prometheus), 3300 (Grafana), 3100 (Loki)
pod-storage SeaweedFS (master, volume, filer, WebDAV) 9333 (master), 8080 (volume), 8888 (filer), 7333 (WebDAV)
host FUSE daemon (FuseMountService gRPC) 50053 — runs on the host as a systemd user service, not in a pod

All pods join the aegis-network bridge network.

FUSE Daemon (Host-Side Storage)

The AEGIS FUSE daemon is a host-side component -- it runs on the host as a systemd user service, not inside a container. It provides native POSIX filesystem access to workspace volumes via the FSAL security boundary.

Rootless Podman containers cannot mount FUSE filesystems internally, so the daemon runs on the host and exposes mountpoints that are bind-mounted into execution containers. This gives agents transparent read/write access to their workspace files.

Architecture

  • Connects to the orchestrator's gRPC endpoint for FSAL operations
  • Mounts workspace volumes as FUSE filesystems on the host
  • Execution containers access files through bind mounts from FUSE mountpoints
  • All operations pass through the FSAL security boundary (tenant isolation, access policies)

Management

The daemon is started automatically by make deploy and managed via systemd:

systemctl --user start aegis-fuse-daemon
systemctl --user stop aegis-fuse-daemon
systemctl --user status aegis-fuse-daemon
journalctl --user -u aegis-fuse-daemon -f   # tail logs

Prerequisites

Requires the fuse3 package and fuse kernel module. The unit runs %h/.local/bin/aegis (extracted from the runtime image into $REPO/bin/aegis). It retries until orchestrator :50051 is up.

Edge Proxy (Optional)

The pod-edge directory contains a Caddy reverse proxy.

Local (default in this repo): HTTP on port 80, auto_https off, no Cloudflare token required. Hostnames use DOMAIN_* from .env (defaults *.localhost).

Subdomain Variable Default Backend (in-pod port)
DOMAIN_API api.localhost aegis-core:8088
DOMAIN_SEAL seal.localhost aegis-seal-gateway:8089
DOMAIN_MCP mcp.localhost aegis-mcp:3000 (host maps 8090→3000)
DOMAIN_TEMPORAL temporal.localhost aegis-temporal:8080
DOMAIN_GRAFANA grafana.localhost aegis-observability:3000 (host maps 3300→3000)
DOMAIN_PROMETHEUS prometheus.localhost aegis-observability:9090
DOMAIN_JAEGER jaeger.localhost aegis-observability:16686
DOMAIN_SECRETS secrets.localhost aegis-secrets:8200

Production TLS: restore Cloudflare ACME (acme_dns cloudflare) and set CLOUDFLARE_API_TOKEN + real DOMAIN_*.

make redeploy POD=edge

Browser access

This checkout is native Linux. http://127.0.0.1:PORT is correct on the host.

If the stack runs in WSL2, a Windows browser http://127.0.0.1:PORT hits Windows, not WSL → connection refused. Use the WSL eth0 IP from hostname -I inside WSL.

See docs/LOCAL-OPS.md for the full UI port list, LLM config, JWT auth, teardown leftovers, and workflow YAML schema.

Local LLM (LM Studio)

podman/pods/core/aegis-config.yaml is prefer-local:

  • Host server: bind 0.0.0.0:1234 (lms server start --bind 0.0.0.0). Infra comes up with no model. make teardown does not stop LM Studio.
  • From pods: http://host.containers.internal:1234/v1
  • Kali + netavark: pasta maps host.containers.internal to 169.254.1.2, which times out from aegis-network. make deploy / make redeploy POD=core rewrite it to the host LAN IP (scripts/patch-host-gateway.sh, optional AEGIS_HOST_LAN_IP).
  • Model: qwen2.5-coder-7b-instruct (Qwen2.5-Coder-7B-Instruct Q4_K_M; confirm with curl -s http://127.0.0.1:1234/v1/models)
  • Load on a 6GB GPU: lms load qwen2.5-coder-7b-instruct --gpu max -c 4096 --parallel 1 -y. Thinking off.
  • Aliases default, slm, smart, judge, slm-judge all point at Qwen Coder 7B (max_output_tokens 2048, 1024 for judge; ctx 4096)
  • Gemini stays enabled: false unless ZARU_LLM_API_KEY is set

After config changes: podman restart aegis-core-aegis-runtime, then make overlays (core start re-registers stock v1.0.0 builtins).

Makefile Targets

Target Description
make setup Install Podman and dependencies (Ubuntu or Kali)
make deploy Deploy all pods for the active profile
make teardown Stop and remove profile pods + FUSE (not LM Studio, not leftover aegis-agent-*)
make status Show running pod status
make validate Run health checks against deployed services
make registry-login Authenticate to ghcr.io using .env credentials
make bootstrap-secrets Initialize OpenBao and populate AppRole credentials
make bootstrap-keycloak Configure Keycloak realm, clients, and roles
make generate-keys Generate SEAL RSA signing key pair
make overlays Re-apply manifests/slow-slm/ agent/workflow versions (after core restart)
make redeploy POD=<name> Tear down and redeploy a single pod
make logs POD=<name> Tail logs for a specific pod
make clean Full teardown + prune volumes and networks

Configuration

Copy .env.example to .env and fill in the required values. Key variables:

Variable Required Description
AEGIS_ROOT Yes Absolute path to this repository checkout
GHCR_USERNAME Yes GitHub username for container registry
GHCR_TOKEN Yes GitHub PAT with read:packages scope
POSTGRES_PASSWORD Yes PostgreSQL password
ZARU_LLM_API_KEY No Gemini key; unused while Gemini is disabled
AEGIS_HOST_LAN_IP No Host IPv4 for host.containers.internal (auto-detected if empty)
KEYCLOAK_ADMIN_PASSWORD Recommended Keycloak admin password (default: changeme)
GRAFANA_ADMIN_PASSWORD Recommended Grafana admin password (default: changeme)
CLOUDFLARE_API_TOKEN Edge only Required for Caddy TLS via DNS challenge

See .env.example for the full list with descriptions.

Using the CLI with a local deployment

After make deploy PROFILE=development (which now includes the iam pod) and make bootstrap-keycloak:

# Non-interactive JWT (AEGIS_API_TOKEN is not a JWT and will 401).
# Client secret from bootstrap-keycloak.sh is "placeholder".
TOKEN=$(curl -sS -X POST 'http://127.0.0.1:8180/realms/aegis-system/protocol/openid-connect/token' \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  -d 'client_id=aegis-runtime&client_secret=placeholder&grant_type=client_credentials' \
  | python3 -c 'import sys,json;print(json.load(sys.stdin)["access_token"])')

# Direct agent execute (in-process — does NOT appear in Temporal UI)
AEGIS_KEY="$TOKEN" aegis --host 127.0.0.1 --port 8088 --output json \
  agent run aegis-python-executor-agent \
  --intent 'Write a Python function fib(n) that returns the first n Fibonacci numbers.'

# Durable workflow (DOES appear at http://127.0.0.1:8233/namespaces/default/workflows)
# --follow needs workflow:logs. Do not pin version 1.0.0 (stock builtin).
AEGIS_KEY="$TOKEN" aegis --host 127.0.0.1 --port 8088 --output json \
  workflow run builtin-intent-to-execution \
  --intent 'Write a Python function fib(n).' \
  --input '{"language":"python","language_ext":"py","runner":"python3","runner_flags":"-s","container_image":"python:3.11-slim","inputs":{"n":10},"inputs_json":"{\"n\":10}"}' \
  --follow

hello-world is deployed but cannot start (schema requires task; the execute path wraps input). Use aegis-python-executor-agent or a Temporal workflow. See docs/LOCAL-OPS.md.

Documentation

Doc What
docs/LOCAL-OPS.md Operator runbook (JWT, LM Studio, overlays, teardown)
manifests/slow-slm/README.md Slow-SLM overlay versions and timeout knobs
docs/AEGIS-Local-SLM-Field-Report-2026-08-21.pdf 2026-08-21 field report (accessible PDF + unified diff)
pc-tuning/summary.md Host I/O scheduler and swappiness notes
AGENTS.md Context for AI assistants (CLAUDE.md is a symlink)

Full platform documentation: https://docs.100monkeys.ai

License

AGPL-3.0-only -- Copyright 2026 100monkeys.ai

About

Full stack deployment of AEGIS from 100monkeys.ai

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages