chore: rebrand farhoodliquor → farhoodlabs, API-only mode, split infra
- Rename org references from farhoodliquor to farhoodlabs in CI workflows and GHCR image tags - Rewrite README for Hightower as API-driven K8s fork of Shannon - Update CLAUDE.md to reflect API-only deployment model - Delete docker-compose files (K8s only, no Docker Compose support) - Delete shannon CLI entry point (API-only going forward) - Move K8s manifests to farhoodlabs/hightower-infra Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -16,7 +16,7 @@ concurrency:
|
||||
jobs:
|
||||
check:
|
||||
name: Type-check & lint
|
||||
runs-on: runners-farhoodliquor
|
||||
runs-on: runners-farhoodlabs
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
@@ -43,7 +43,7 @@ jobs:
|
||||
name: Build & push worker image
|
||||
needs: check
|
||||
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
|
||||
runs-on: runners-farhoodliquor
|
||||
runs-on: runners-farhoodlabs
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
@@ -68,14 +68,14 @@ jobs:
|
||||
context: .
|
||||
push: true
|
||||
tags: |
|
||||
ghcr.io/farhoodliquor/shannon:latest
|
||||
ghcr.io/farhoodliquor/shannon:sha-${{ github.sha }}
|
||||
ghcr.io/farhoodlabs/shannon:latest
|
||||
ghcr.io/farhoodlabs/shannon:sha-${{ github.sha }}
|
||||
|
||||
build-api:
|
||||
name: Build & push API image
|
||||
needs: check
|
||||
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
|
||||
runs-on: runners-farhoodliquor
|
||||
runs-on: runners-farhoodlabs
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
@@ -102,5 +102,5 @@ jobs:
|
||||
push: true
|
||||
no-cache: true
|
||||
tags: |
|
||||
ghcr.io/farhoodliquor/hightower-api:latest
|
||||
ghcr.io/farhoodliquor/hightower-api:sha-${{ github.sha }}
|
||||
ghcr.io/farhoodlabs/hightower-api:latest
|
||||
ghcr.io/farhoodlabs/hightower-api:sha-${{ github.sha }}
|
||||
|
||||
@@ -13,7 +13,7 @@ concurrency:
|
||||
jobs:
|
||||
preflight:
|
||||
name: Preflight
|
||||
runs-on: runners-farhoodliquor
|
||||
runs-on: runners-farhoodlabs
|
||||
outputs:
|
||||
version: ${{ steps.version.outputs.version }}
|
||||
|
||||
@@ -47,7 +47,7 @@ jobs:
|
||||
build-docker:
|
||||
name: Build Docker (worker)
|
||||
needs: preflight
|
||||
runs-on: runners-farhoodliquor
|
||||
runs-on: runners-farhoodlabs
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
@@ -76,7 +76,7 @@ jobs:
|
||||
build-docker-api:
|
||||
name: Build Docker (API)
|
||||
needs: preflight
|
||||
runs-on: runners-farhoodliquor
|
||||
runs-on: runners-farhoodlabs
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
@@ -106,7 +106,7 @@ jobs:
|
||||
sign-docker:
|
||||
name: Sign Docker images
|
||||
needs: [preflight, build-docker, build-docker-api]
|
||||
runs-on: runners-farhoodliquor
|
||||
runs-on: runners-farhoodlabs
|
||||
permissions:
|
||||
contents: read
|
||||
id-token: write
|
||||
@@ -165,7 +165,7 @@ jobs:
|
||||
publish-npm:
|
||||
name: Publish npm (beta)
|
||||
needs: [preflight, sign-docker]
|
||||
runs-on: runners-farhoodliquor
|
||||
runs-on: runners-farhoodlabs
|
||||
permissions:
|
||||
contents: read
|
||||
id-token: write
|
||||
|
||||
@@ -13,7 +13,7 @@ concurrency:
|
||||
jobs:
|
||||
preflight:
|
||||
name: Preflight
|
||||
runs-on: runners-farhoodliquor
|
||||
runs-on: runners-farhoodlabs
|
||||
permissions:
|
||||
contents: write
|
||||
outputs:
|
||||
@@ -60,7 +60,7 @@ jobs:
|
||||
name: Build Docker (worker)
|
||||
needs: preflight
|
||||
if: needs.preflight.outputs.should_release == 'true'
|
||||
runs-on: runners-farhoodliquor
|
||||
runs-on: runners-farhoodlabs
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
@@ -92,7 +92,7 @@ jobs:
|
||||
name: Build Docker (API)
|
||||
needs: preflight
|
||||
if: needs.preflight.outputs.should_release == 'true'
|
||||
runs-on: runners-farhoodliquor
|
||||
runs-on: runners-farhoodlabs
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
@@ -124,7 +124,7 @@ jobs:
|
||||
sign-docker:
|
||||
name: Sign Docker images
|
||||
needs: [preflight, build-docker, build-docker-api]
|
||||
runs-on: runners-farhoodliquor
|
||||
runs-on: runners-farhoodlabs
|
||||
permissions:
|
||||
contents: read
|
||||
id-token: write
|
||||
@@ -183,7 +183,7 @@ jobs:
|
||||
publish-npm:
|
||||
name: Publish npm
|
||||
needs: [preflight, sign-docker]
|
||||
runs-on: runners-farhoodliquor
|
||||
runs-on: runners-farhoodlabs
|
||||
permissions:
|
||||
contents: read
|
||||
id-token: write
|
||||
@@ -228,7 +228,7 @@ jobs:
|
||||
release:
|
||||
name: Create GitHub release
|
||||
needs: [preflight, publish-npm]
|
||||
runs-on: runners-farhoodliquor
|
||||
runs-on: runners-farhoodlabs
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ concurrency:
|
||||
jobs:
|
||||
rollback:
|
||||
name: Roll back npm beta dist-tag
|
||||
runs-on: runners-farhoodliquor
|
||||
runs-on: runners-farhoodlabs
|
||||
steps:
|
||||
- name: Validate target version
|
||||
id: target
|
||||
|
||||
@@ -18,7 +18,7 @@ concurrency:
|
||||
jobs:
|
||||
rollback:
|
||||
name: Roll back npm, Docker, and GitHub release latest
|
||||
runs-on: runners-farhoodliquor
|
||||
runs-on: runners-farhoodlabs
|
||||
steps:
|
||||
- name: Checkout tags
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
|
||||
@@ -1,78 +1,12 @@
|
||||
# CLAUDE.md
|
||||
|
||||
AI-powered penetration testing agent for defensive security analysis. Automates vulnerability assessment by combining reconnaissance tools with AI-powered code analysis.
|
||||
Hightower is a fork of [Shannon](https://github.com/KeygraphHQ/shannon) by Keygraph — an AI-powered penetration testing agent for defensive security analysis. It wraps Shannon's autonomous pentesting engine with a REST API and Kubernetes deployment tooling.
|
||||
|
||||
**Upstream policy:** `apps/cli/` and `apps/worker/` are kept as close to upstream Shannon as possible for backporting. Only `apps/api/`, CI/CD workflows, and infra are Hightower-specific.
|
||||
|
||||
## Commands
|
||||
|
||||
**Prerequisites:** Docker, AI provider credentials (`.env` for local, `shn setup` or env vars for npx)
|
||||
|
||||
### Dual CLI
|
||||
|
||||
Shannon supports two CLI modes, auto-detected based on the current working directory:
|
||||
|
||||
| | **npx** (`npx @keygraph/shannon`) | **Local** (`./shannon`) |
|
||||
|---|---|---|
|
||||
| **Install** | Zero-install via npm | Clone the repo |
|
||||
| **Image** | Pulled from Docker Hub (`keygraph/shannon:latest`) | Built locally (`shannon-worker`) |
|
||||
| **State** | `~/.shannon/` | Project directory |
|
||||
| **Credentials** | `~/.shannon/config.toml` (via `shn setup`) or env vars | `./.env` |
|
||||
| **Config** | `~/.shannon/config.toml` (via `shn setup`) | N/A |
|
||||
| **Prompts** | Bundled in Docker image | Mounted from `./apps/worker/prompts/` (live-editable) |
|
||||
|
||||
Mode auto-detection: local mode activates when env var `SHANNON_LOCAL=1` is set by the `./shannon` entry point (`apps/cli/src/mode.ts`). Otherwise npx mode.
|
||||
|
||||
### npx Quick Start
|
||||
|
||||
```bash
|
||||
# Configure credentials (interactive wizard)
|
||||
npx @keygraph/shannon setup
|
||||
|
||||
# Or export env vars directly (non-interactive / CI)
|
||||
export ANTHROPIC_API_KEY=your-key
|
||||
|
||||
# Run
|
||||
npx @keygraph/shannon start -u <url> -r /path/to/repo
|
||||
```
|
||||
|
||||
### Local (Development) Quick Start
|
||||
|
||||
```bash
|
||||
# Setup
|
||||
echo "ANTHROPIC_API_KEY=your-key" > .env
|
||||
|
||||
# Build (auto-runs if image missing)
|
||||
./shannon build
|
||||
|
||||
# Run
|
||||
./shannon start -u <url> -r my-repo
|
||||
./shannon start -u <url> -r my-repo -c ./apps/worker/configs/my-config.yaml
|
||||
./shannon start -u <url> -r /any/path/to/repo
|
||||
```
|
||||
|
||||
### Common Commands
|
||||
|
||||
```bash
|
||||
# Setup (npx mode only — one-time credential configuration)
|
||||
npx @keygraph/shannon setup
|
||||
|
||||
# Workspaces & Resume
|
||||
./shannon start -u <url> -r my-repo -w my-audit # New named workspace
|
||||
./shannon start -u <url> -r my-repo -w my-audit # Resume (same command)
|
||||
./shannon workspaces # List all workspaces
|
||||
|
||||
# Monitor
|
||||
./shannon logs <workspace> # Tail workflow log
|
||||
./shannon status # Show running workers
|
||||
# Temporal Web UI: http://localhost:8233
|
||||
|
||||
# Stop
|
||||
./shannon stop # Preserves workflow data
|
||||
./shannon stop --clean # Full cleanup including volumes (confirms first)
|
||||
|
||||
# Image management
|
||||
./shannon build [--no-cache] # Local mode: build worker image
|
||||
npx @keygraph/shannon uninstall # npx mode: remove ~/.shannon/ (confirms first)
|
||||
|
||||
# Build TypeScript (development)
|
||||
pnpm run build # Build all packages via Turborepo
|
||||
pnpm run check # Type-check all packages
|
||||
@@ -82,42 +16,25 @@ pnpm biome:fix # Auto-fix lint, format, and import sorting
|
||||
|
||||
**Monorepo tooling:** pnpm workspaces, Turborepo for task orchestration, Biome for linting/formatting. TypeScript compiler options shared via `tsconfig.base.json` at the root. All packages extend it, overriding only `rootDir` and `outDir`. Shared devDependencies (`typescript`, `@types/node`, `turbo`, `@biomejs/biome`) are hoisted to the root workspace.
|
||||
|
||||
**Options:** `-c <file>` (YAML config), `-o <path>` (output directory), `-w <name>` (named workspace; auto-resumes if exists), `--pipeline-testing` (minimal prompts, 10s retries), `--router` (multi-model routing via [claude-code-router](https://github.com/musistudio/claude-code-router))
|
||||
|
||||
## Architecture
|
||||
|
||||
### Monorepo Layout
|
||||
|
||||
```
|
||||
apps/cli/ — @keygraph/shannon (published to npm, bundled with tsdown)
|
||||
apps/worker/ — @shannon/worker (private, Temporal worker + pipeline logic)
|
||||
apps/api/ — @shannon/api (Hightower REST API, K8s-native)
|
||||
apps/cli/ — @keygraph/shannon (upstream CLI, not used in production)
|
||||
apps/worker/ — @shannon/worker (upstream Temporal worker + pipeline logic)
|
||||
```
|
||||
|
||||
### API Package (`apps/api/`)
|
||||
Hightower-specific REST API for triggering and managing pentests. Deployed on Kubernetes.
|
||||
|
||||
### CLI Package (`apps/cli/`)
|
||||
Published as `@keygraph/shannon` on npm. Contains only Docker orchestration logic — no Temporal SDK, business logic, or prompts. Bundled with tsdown for single-file ESM output.
|
||||
|
||||
- `apps/cli/src/index.ts` — CLI dispatcher (`setup`, `start`, `stop`, `logs`, `workspaces`, `status`, `build`, `uninstall`, `info`)
|
||||
- `apps/cli/src/mode.ts` — Auto-detection: local mode if `SHANNON_LOCAL=1` env var is set
|
||||
- `apps/cli/src/docker.ts` — Compose lifecycle, image pull/build, ephemeral `docker run` worker spawning
|
||||
- `apps/cli/src/home.ts` — State directory management (`~/.shannon/` for npx, `./` for local)
|
||||
- `apps/cli/src/env.ts` — `.env` loading, TOML fallback (npx only) via `apps/cli/src/config/resolver.ts`, credential validation, env flag building
|
||||
- `apps/cli/src/config/resolver.ts` — Cascading config (npx only): env vars → `~/.shannon/config.toml` (parsed with `smol-toml`)
|
||||
- `apps/cli/src/config/writer.ts` — TOML serialization and secure file persistence (0o600)
|
||||
- `apps/cli/src/commands/setup.ts` — Interactive TUI wizard (`@clack/prompts`) for provider credential setup (npx only)
|
||||
- `apps/cli/src/paths.ts` — Repo/config path resolution (bare name → `./repos/<name>`, or any absolute/relative path)
|
||||
- `apps/cli/src/commands/` — Command handlers
|
||||
- `apps/cli/infra/compose.yml` — Bundled Temporal + router compose file for npx mode
|
||||
- `apps/cli/tsdown.config.ts` — tsdown bundler config
|
||||
- `shannon` — Node.js entry point (`#!/usr/bin/env node`) that delegates to `apps/cli/dist/index.mjs`
|
||||
|
||||
### Docker Architecture
|
||||
Infra (Temporal + router) runs via `docker-compose.yml`. Workers are ephemeral `docker run --rm` containers, one per scan, each with a unique task queue and isolated volume mounts.
|
||||
|
||||
- `docker-compose.yml` — Infra only: `shannon-temporal` (port 7233/8233) and `shannon-router` (port 3456, optional via profile). Network: `shannon-net`
|
||||
- `Dockerfile` — 2-stage build (builder + Chainguard Wolfi runtime). Uses pnpm. Entrypoint: `CMD ["node", "apps/worker/dist/temporal/worker.js"]`
|
||||
- No `docker-compose.docker.yml` — host gateway handled via `--add-host` flag in CLI
|
||||
Upstream Shannon CLI — kept for backporting compatibility. Not used in Hightower's K8s deployment.
|
||||
|
||||
### Worker Package (`apps/worker/`)
|
||||
Upstream Shannon worker — Temporal worker + pipeline logic. Runs as ephemeral K8s Jobs.
|
||||
|
||||
- `apps/worker/src/paths.ts` — Centralized path constants (`PROMPTS_DIR`, `CONFIGS_DIR`, `WORKSPACES_DIR`)
|
||||
- `apps/worker/src/session-manager.ts` — Agent definitions (`AGENTS` record). Agent types in `apps/worker/src/types/agents.ts`
|
||||
- `apps/worker/src/config-parser.ts` — YAML config parsing with JSON Schema validation
|
||||
@@ -135,6 +52,7 @@ Durable workflow orchestration with crash recovery, queryable progress, intellig
|
||||
- `apps/worker/src/temporal/summary-mapper.ts` — Maps `PipelineSummary` to `WorkflowSummary`
|
||||
- `apps/worker/src/temporal/worker.ts` — Combined worker + client entry point (per-invocation task queue, submits workflow, waits for result)
|
||||
- `apps/worker/src/temporal/shared.ts` — Types, interfaces, query definitions
|
||||
|
||||
### Five-Phase Pipeline
|
||||
|
||||
1. **Pre-Recon** (`pre-recon`) — External scans (nmap, subfinder, whatweb) + source code analysis
|
||||
@@ -143,8 +61,15 @@ Durable workflow orchestration with crash recovery, queryable progress, intellig
|
||||
4. **Exploitation** (5 parallel agents, conditional) — Exploits confirmed vulnerabilities
|
||||
5. **Reporting** (`report`) — Executive-level security report
|
||||
|
||||
### Docker Images
|
||||
- `Dockerfile` — Worker image: 2-stage build (builder + Chainguard Wolfi runtime). Uses pnpm. Entrypoint: `CMD ["node", "apps/worker/dist/temporal/worker.js"]`
|
||||
- `apps/api/Dockerfile` — API image: minimal Alpine build
|
||||
|
||||
### Kubernetes Infrastructure
|
||||
K8s manifests live in a separate repository: [farhoodlabs/hightower-infra](https://github.com/farhoodlabs/hightower-infra).
|
||||
|
||||
### Supporting Systems
|
||||
- **Configuration** — YAML configs in `apps/worker/configs/` with JSON Schema validation (`config-schema.json`). Supports auth settings, MFA/TOTP, and per-app testing parameters. Credential resolution — local mode: env vars → `./.env`; npx mode: env vars → `~/.shannon/config.toml` (via `shn setup`)
|
||||
- **Configuration** — YAML configs in `apps/worker/configs/` with JSON Schema validation (`config-schema.json`). Supports auth settings, MFA/TOTP, and per-app testing parameters
|
||||
- **Prompts** — Per-phase templates in `apps/worker/prompts/` with variable substitution (`{{TARGET_URL}}`, `{{CONFIG_CONTEXT}}`). Shared partials in `apps/worker/prompts/shared/` via `apps/worker/src/services/prompt-manager.ts`
|
||||
- **SDK Integration** — Uses `@anthropic-ai/claude-agent-sdk` with `maxTurns: 10_000` and `bypassPermissions` mode. Browser automation via `playwright-cli` with session isolation (`-s=<session>`). TOTP generation via `generate-totp` CLI tool. Login flow template at `apps/worker/prompts/shared/login-instructions.txt` supports form, SSO, API, and basic auth
|
||||
- **Audit System** — Crash-safe append-only logging in `workspaces/{hostname}_{sessionId}/`. Tracks session metrics, per-agent logs, prompts, and deliverables. WorkflowLogger (`apps/worker/src/audit/workflow-logger.ts`) provides unified human-readable per-workflow logs, backed by LogStream (`apps/worker/src/audit/log-stream.ts`) shared stream primitive
|
||||
@@ -171,7 +96,7 @@ Durable workflow orchestration with crash recovery, queryable progress, intellig
|
||||
- **Modular Error Handling** — `ErrorCode` enum, `Result<T,E>` for explicit error propagation, automatic retry (3 attempts per agent)
|
||||
- **Services Boundary** — Activities are thin Temporal wrappers; `apps/worker/src/services/` owns business logic, accepts `ActivityLogger`, returns `Result<T,E>`. No Temporal imports in services
|
||||
- **DI Container** — Per-workflow in `apps/worker/src/services/container.ts`. `AuditSession` excluded (parallel safety)
|
||||
- **Ephemeral Workers** — Each scan runs in its own `docker run --rm` container with a per-invocation task queue. Temporal routes activities by queue name, so per-scan queues ensure activities never land on a worker with the wrong repo mounted
|
||||
- **Ephemeral Workers** — Each scan runs in its own container with a per-invocation task queue. Temporal routes activities by queue name, so per-scan queues ensure activities never land on a worker with the wrong repo mounted
|
||||
|
||||
### Security
|
||||
Defensive security tool only. Use only on systems you own or have explicit permission to test.
|
||||
@@ -223,26 +148,16 @@ Comments must be **timeless** — no references to this conversation, refactorin
|
||||
|
||||
## Key Files
|
||||
|
||||
**CLI:** `shannon` (entry point), `apps/cli/src/index.ts` (dispatcher), `apps/cli/src/docker.ts` (orchestration), `apps/cli/src/mode.ts` (auto-detection)
|
||||
**API:** `apps/api/src/` (Hightower REST API), `apps/api/Dockerfile`
|
||||
|
||||
**Entry Points:** `apps/worker/src/temporal/workflows.ts`, `apps/worker/src/temporal/activities.ts`, `apps/worker/src/temporal/worker.ts`
|
||||
|
||||
**Core Logic:** `apps/worker/src/session-manager.ts`, `apps/worker/src/ai/claude-executor.ts`, `apps/worker/src/config-parser.ts`, `apps/worker/src/services/`, `apps/worker/src/audit/`
|
||||
|
||||
**Config:** `docker-compose.yml`, `apps/cli/infra/compose.yml`, `apps/worker/configs/`, `apps/worker/prompts/`, `tsconfig.base.json` (shared compiler options), `turbo.json`, `biome.json`
|
||||
**Config:** `Dockerfile`, `apps/worker/configs/`, `apps/worker/prompts/`, `tsconfig.base.json` (shared compiler options), `turbo.json`, `biome.json`
|
||||
|
||||
**CI/CD:** `.github/workflows/release.yml` (Docker Hub push + npm publish + GitHub release, manual dispatch)
|
||||
**CI/CD:** `.github/workflows/ci.yml` (type-check, lint, build & push images to GHCR), `.github/workflows/release.yml` (Docker Hub push + GitHub release, manual dispatch)
|
||||
|
||||
## Package Installation
|
||||
|
||||
Package managers are configured with a minimum release age (7 days). Requires pnpm >= 10.16.0. If `pnpm install` fails due to a package being too new, **do not attempt to bypass it** — report the blocked package to the user and stop.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
- **"Repository not found"** — Pass a bare name (`-r my-repo`) for `./repos/my-repo`, or a path (`-r /path/to/repo`) for any directory
|
||||
- **"Temporal not ready"** — Wait for health check or `docker compose logs temporal`
|
||||
- **Worker not processing** — Check `docker ps --filter "name=shannon-worker-"`
|
||||
- **Reset state** — `./shannon stop --clean`
|
||||
- **Local apps unreachable** — Use `host.docker.internal` instead of `localhost`
|
||||
- **Missing tools** — Use `--pipeline-testing` to skip nmap/subfinder/whatweb (graceful degradation)
|
||||
- **Container permissions** — On Linux, may need `sudo` for docker commands
|
||||
|
||||
@@ -1,62 +0,0 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: hightower-api
|
||||
namespace: hightower
|
||||
labels:
|
||||
app: hightower-api
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: hightower-api
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: hightower-api
|
||||
annotations:
|
||||
kubectl.kubernetes.io/restartedAt: "2026-04-21T22:21:00Z"
|
||||
spec:
|
||||
serviceAccountName: hightower-api
|
||||
containers:
|
||||
- name: api
|
||||
image: ghcr.io/farhoodliquor/hightower-api:sha-a0efe7604ebc2f27cc37ee88f117ae619e57003f
|
||||
imagePullPolicy: Always
|
||||
ports:
|
||||
- containerPort: 3000
|
||||
name: http
|
||||
env:
|
||||
- name: TEMPORAL_ADDRESS
|
||||
value: hightower-temporal:7233
|
||||
- name: WORKER_IMAGE
|
||||
value: ghcr.io/farhoodliquor/shannon:latest
|
||||
- name: K8S_NAMESPACE
|
||||
value: hightower
|
||||
envFrom:
|
||||
- secretRef:
|
||||
name: hightower-credentials
|
||||
volumeMounts:
|
||||
- name: workspaces
|
||||
mountPath: /app/workspaces
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /healthz
|
||||
port: 3000
|
||||
initialDelaySeconds: 5
|
||||
periodSeconds: 10
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /readyz
|
||||
port: 3000
|
||||
initialDelaySeconds: 10
|
||||
periodSeconds: 10
|
||||
resources:
|
||||
requests:
|
||||
memory: 128Mi
|
||||
cpu: 100m
|
||||
limits:
|
||||
memory: 256Mi
|
||||
volumes:
|
||||
- name: workspaces
|
||||
persistentVolumeClaim:
|
||||
claimName: hightower-workspaces
|
||||
@@ -1,7 +0,0 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- deployment.yaml
|
||||
- service.yaml
|
||||
- serviceaccount.yaml
|
||||
- rbac.yaml
|
||||
@@ -1,53 +0,0 @@
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: Role
|
||||
metadata:
|
||||
name: hightower-api
|
||||
namespace: hightower
|
||||
rules:
|
||||
- apiGroups: ["batch"]
|
||||
resources: ["jobs"]
|
||||
verbs: ["create", "get", "list", "delete", "watch"]
|
||||
- apiGroups: [""]
|
||||
resources: ["pods"]
|
||||
verbs: ["get", "list", "watch"]
|
||||
- apiGroups: [""]
|
||||
resources: ["pods/log"]
|
||||
verbs: ["get"]
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: RoleBinding
|
||||
metadata:
|
||||
name: hightower-api
|
||||
namespace: hightower
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: hightower-api
|
||||
namespace: hightower
|
||||
roleRef:
|
||||
kind: Role
|
||||
name: hightower-api
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: Role
|
||||
metadata:
|
||||
name: hightower-deploy-manager
|
||||
namespace: hightower
|
||||
rules:
|
||||
- apiGroups: ["apps"]
|
||||
resources: ["deployments"]
|
||||
verbs: ["get", "list", "watch", "update", "patch"]
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: RoleBinding
|
||||
metadata:
|
||||
name: farh-net-deploy-manager
|
||||
namespace: hightower
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: farh-net-paperclip
|
||||
namespace: farh-net
|
||||
roleRef:
|
||||
kind: Role
|
||||
name: hightower-deploy-manager
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
@@ -1,12 +0,0 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: hightower-api
|
||||
namespace: hightower
|
||||
spec:
|
||||
selector:
|
||||
app: hightower-api
|
||||
ports:
|
||||
- name: http
|
||||
port: 3000
|
||||
targetPort: 3000
|
||||
@@ -1,5 +0,0 @@
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: hightower-api
|
||||
namespace: hightower
|
||||
@@ -1,16 +0,0 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- ../../base
|
||||
patches:
|
||||
- patch: |-
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: hightower-api
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: api
|
||||
imagePullPolicy: Never
|
||||
@@ -1,50 +0,0 @@
|
||||
networks:
|
||||
default:
|
||||
name: shannon-net
|
||||
|
||||
services:
|
||||
temporal:
|
||||
image: temporalio/temporal:latest
|
||||
container_name: shannon-temporal
|
||||
command: ["server", "start-dev", "--db-filename", "/home/temporal/temporal.db", "--ip", "0.0.0.0"]
|
||||
ports:
|
||||
- "127.0.0.1:7233:7233"
|
||||
- "127.0.0.1:8233:8233"
|
||||
volumes:
|
||||
- temporal-data:/home/temporal
|
||||
healthcheck:
|
||||
test: ["CMD", "temporal", "operator", "cluster", "health", "--address", "localhost:7233"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 10
|
||||
start_period: 30s
|
||||
|
||||
router:
|
||||
image: node:20-slim
|
||||
container_name: shannon-router
|
||||
profiles: ["router"]
|
||||
command: >
|
||||
sh -c "apt-get update && apt-get install -y gettext-base &&
|
||||
npm install -g @musistudio/claude-code-router &&
|
||||
mkdir -p /root/.claude-code-router &&
|
||||
envsubst < /config/router-config.json > /root/.claude-code-router/config.json &&
|
||||
ccr start"
|
||||
ports:
|
||||
- "127.0.0.1:3456:3456"
|
||||
volumes:
|
||||
- ./router-config.json:/config/router-config.json:ro
|
||||
environment:
|
||||
- HOST=0.0.0.0
|
||||
- ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY:-}
|
||||
- OPENAI_API_KEY=${OPENAI_API_KEY:-}
|
||||
- OPENROUTER_API_KEY=${OPENROUTER_API_KEY:-}
|
||||
- ROUTER_DEFAULT=${ROUTER_DEFAULT:-openai,gpt-4o}
|
||||
healthcheck:
|
||||
test: ["CMD", "node", "-e", "require('http').get('http://localhost:3456/health', r => process.exit(r.statusCode === 200 ? 0 : 1)).on('error', () => process.exit(1))"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
start_period: 30s
|
||||
|
||||
volumes:
|
||||
temporal-data:
|
||||
@@ -1,69 +0,0 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: hightower-router
|
||||
namespace: hightower
|
||||
labels:
|
||||
app: hightower-router
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: hightower-router
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: hightower-router
|
||||
spec:
|
||||
containers:
|
||||
- name: router
|
||||
image: node:20-slim
|
||||
command:
|
||||
- sh
|
||||
- -c
|
||||
- |
|
||||
apt-get update && apt-get install -y gettext-base &&
|
||||
npm install -g @musistudio/claude-code-router &&
|
||||
mkdir -p /root/.claude-code-router &&
|
||||
envsubst < /config/router-config.json > /root/.claude-code-router/config.json &&
|
||||
ccr start
|
||||
ports:
|
||||
- containerPort: 3456
|
||||
envFrom:
|
||||
- secretRef:
|
||||
name: hightower-credentials
|
||||
env:
|
||||
- name: HOST
|
||||
value: "0.0.0.0"
|
||||
volumeMounts:
|
||||
- name: config
|
||||
mountPath: /config
|
||||
readOnly: true
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /health
|
||||
port: 3456
|
||||
initialDelaySeconds: 30
|
||||
periodSeconds: 10
|
||||
timeoutSeconds: 5
|
||||
failureThreshold: 5
|
||||
resources:
|
||||
requests:
|
||||
memory: 128Mi
|
||||
cpu: 100m
|
||||
volumes:
|
||||
- name: config
|
||||
configMap:
|
||||
name: hightower-router-config
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: hightower-router
|
||||
namespace: hightower
|
||||
spec:
|
||||
selector:
|
||||
app: hightower-router
|
||||
ports:
|
||||
- port: 3456
|
||||
targetPort: 3456
|
||||
@@ -1,98 +0,0 @@
|
||||
# CNPG PostgreSQL cluster for Temporal persistence
|
||||
apiVersion: postgresql.cnpg.io/v1
|
||||
kind: Cluster
|
||||
metadata:
|
||||
name: hightower-temporal-db
|
||||
namespace: hightower
|
||||
spec:
|
||||
instances: 1
|
||||
storage:
|
||||
size: 5Gi
|
||||
storageClass: ceph-block
|
||||
bootstrap:
|
||||
initdb:
|
||||
database: temporal
|
||||
owner: temporal
|
||||
postInitSQL:
|
||||
- CREATE DATABASE temporal_visibility OWNER temporal;
|
||||
---
|
||||
# Temporal auto-setup — handles schema creation/migration automatically
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: hightower-temporal
|
||||
namespace: hightower
|
||||
labels:
|
||||
app: hightower-temporal
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: hightower-temporal
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: hightower-temporal
|
||||
spec:
|
||||
containers:
|
||||
- name: temporal
|
||||
image: temporalio/auto-setup:latest
|
||||
ports:
|
||||
- containerPort: 7233
|
||||
name: grpc
|
||||
- containerPort: 8233
|
||||
name: web-ui
|
||||
env:
|
||||
- name: DB
|
||||
value: postgres12
|
||||
- name: DB_PORT
|
||||
value: "5432"
|
||||
- name: POSTGRES_SEEDS
|
||||
value: hightower-temporal-db-rw
|
||||
- name: DBNAME
|
||||
value: temporal
|
||||
- name: VISIBILITY_DBNAME
|
||||
value: temporal_visibility
|
||||
- name: POSTGRES_USER
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: hightower-temporal-db-app
|
||||
key: username
|
||||
- name: POSTGRES_PWD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: hightower-temporal-db-app
|
||||
key: password
|
||||
- name: NUM_HISTORY_SHARDS
|
||||
value: "4"
|
||||
- name: SKIP_DB_CREATE
|
||||
value: "true"
|
||||
readinessProbe:
|
||||
tcpSocket:
|
||||
port: 7233
|
||||
initialDelaySeconds: 30
|
||||
periodSeconds: 10
|
||||
timeoutSeconds: 5
|
||||
failureThreshold: 15
|
||||
resources:
|
||||
requests:
|
||||
memory: 512Mi
|
||||
cpu: 250m
|
||||
limits:
|
||||
memory: 1Gi
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: hightower-temporal
|
||||
namespace: hightower
|
||||
spec:
|
||||
selector:
|
||||
app: hightower-temporal
|
||||
ports:
|
||||
- name: grpc
|
||||
port: 7233
|
||||
targetPort: 7233
|
||||
- name: web-ui
|
||||
port: 8233
|
||||
targetPort: 8233
|
||||
@@ -1,12 +0,0 @@
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: hightower-workspaces
|
||||
namespace: hightower
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteMany
|
||||
storageClassName: ceph-filesystem
|
||||
resources:
|
||||
requests:
|
||||
storage: 10Gi
|
||||
@@ -1,52 +0,0 @@
|
||||
networks:
|
||||
default:
|
||||
name: shannon-net
|
||||
|
||||
services:
|
||||
temporal:
|
||||
image: temporalio/temporal:latest
|
||||
container_name: shannon-temporal
|
||||
command: ["server", "start-dev", "--db-filename", "/home/temporal/temporal.db", "--ip", "0.0.0.0"]
|
||||
ports:
|
||||
- "127.0.0.1:7233:7233" # gRPC
|
||||
- "127.0.0.1:8233:8233" # Web UI (built-in)
|
||||
volumes:
|
||||
- temporal-data:/home/temporal
|
||||
healthcheck:
|
||||
test: ["CMD", "temporal", "operator", "cluster", "health", "--address", "localhost:7233"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 10
|
||||
start_period: 30s
|
||||
|
||||
# Optional: claude-code-router for multi-model support
|
||||
# Start with: ROUTER=true ./shannon start ...
|
||||
router:
|
||||
image: node:20-slim
|
||||
container_name: shannon-router
|
||||
profiles: ["router"] # Only starts when explicitly requested
|
||||
command: >
|
||||
sh -c "apt-get update && apt-get install -y gettext-base &&
|
||||
npm install -g @musistudio/claude-code-router &&
|
||||
mkdir -p /root/.claude-code-router &&
|
||||
envsubst < /config/router-config.json > /root/.claude-code-router/config.json &&
|
||||
ccr start"
|
||||
ports:
|
||||
- "127.0.0.1:3456:3456"
|
||||
volumes:
|
||||
- ./apps/cli/infra/router-config.json:/config/router-config.json:ro
|
||||
environment:
|
||||
- HOST=0.0.0.0
|
||||
- ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY:-}
|
||||
- OPENAI_API_KEY=${OPENAI_API_KEY:-}
|
||||
- OPENROUTER_API_KEY=${OPENROUTER_API_KEY:-}
|
||||
- ROUTER_DEFAULT=${ROUTER_DEFAULT:-openai,gpt-4o}
|
||||
healthcheck:
|
||||
test: ["CMD", "node", "-e", "require('http').get('http://localhost:3456/health', r => process.exit(r.statusCode === 200 ? 0 : 1)).on('error', () => process.exit(1))"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
start_period: 30s
|
||||
|
||||
volumes:
|
||||
temporal-data:
|
||||
Reference in New Issue
Block a user