Repository navigation
Development
Phase 1–5 of the product are implemented: mTLS agent channel, SSE live logs, session auth + RBAC, secrets, connectors (nginx/systemd/Docker/pm2), notifications, web terminal.
- Go 1.25+
- Node 20+ (Next.js 16)
- PostgreSQL 16 — local server, or
make db-upfor Docker - Only when regenerating proto:
protocplusprotoc-gen-goandprotoc-gen-go-grpc
make db-up # start Postgres in Docker (skip if you run a local Postgres)
make migrate # apply migrations
make tidy # pull Go deps for all modules
export SESSION_SECRET="$(openssl rand -hex 32)"
export SEED_ADMIN_EMAIL="you@example.com"
export SEED_ADMIN_PASSWORD="change-me"
# control plane: REST on :8080, mTLS gRPC on :9090
make control-plane && ./control-plane/bin/control-plane
# web UI on :3000 under /app (another shell)
make web
# agent (another shell, on the target or the same box)
make agent
./agent/bin/agent enroll --token=<paste from UI>
./agent/bin/agent runThere is also ./setup.sh / make setup for an interactive local setup.
- Open http://localhost:3000/app. In
next devgo to/appdirectly — only the production control plane redirects/→/app. Sign in with the seeded admin. - Add server, copy the install command (one-time token).
- On the target:
agent enroll --token=...thenagent run. The server row flips toonline. - New job, write a script and a cron, save. Click Run now.
- The run page opens an SSE stream and shows log chunks live.
| Target | Purpose |
|---|---|
db-up / db-down
|
Postgres via docker-compose.yml
|
migrate |
Apply migrations/*.sql with local psql
|
migrate-tool |
Build the bundled migrate binary (no psql required) |
proto / proto-check
|
Regenerate / CI-guard protobuf Go |
control-plane / agent / cli
|
Build binaries |
web |
npm install + next dev
|
tidy |
go mod tidy in each module |
pm2-start / pm2-restart / pm2-status / pm2-logs
|
Supervise a built tree |
install / uninstall
|
From-source installer wrappers |
- Seeded admin is upserted on every boot from
SEED_ADMIN_*asowner. - Cookie:
cc_session. - Open:
/healthz,/api/v1/auth/login,/api/v1/agents/enroll.
First start writes ca.crt, ca.key, server.crt, server.key under TLS_DIR (default ./tls). Agents store agent.key, agent.crt, ca.crt under DATA_DIR/tls/. Subsequent starts load whatever is on disk.
agentgw.LogBroker fans LogChunks to subscribers keyed by run_id. GET /api/v1/runs/:id/logs/stream writes a snapshot, then live log events, then done. The run page uses EventSource and closes on done.
Control plane:
| Var | Default |
|---|---|
DATABASE_URL |
local dev DSN |
HTTP_ADDR |
:8080 |
GRPC_ADDR |
:9090 |
TLS_DIR |
./tls |
TLS_HOSTS |
localhost,127.0.0.1 |
SESSION_SECRET |
must be set in anything non-toy |
PUBLIC_HTTP_URL |
http://localhost:8080/api/v1 |
PUBLIC_GRPC_ADDR |
localhost:9090 |
Agent:
| Var | Default |
|---|---|
CONTROL_PLANE_ADDR |
localhost:9090 |
CONTROL_PLANE_HTTP |
http://localhost:8080/api/v1 |
CONTROL_PLANE_SNI |
localhost |
DATA_DIR |
/var/lib/croncompose |
API_BASE is inlined at Next.js build time by next.config.ts. Set it for npm run build, not only at runtime.
.github/workflows/ci.yml on main and PRs:
- Proto freshness + complete
go.sumforproto,control-plane,agent,cli -
go vet,go test -race,go buildper module - Control-plane REST integration test against Postgres 16
- Web TypeScript check (
tsc --noEmit) on Node 20
Tag v* runs release.yml: static linux/amd64 and linux/arm64 agent binaries plus .deb / .apk.
.
├── DEVELOPMENT.md
├── docs/
├── proto/
├── migrations/
├── control-plane/ Fiber REST + mTLS gRPC
│ └── internal/
│ ├── api/ router, auth gating, web proxy
│ ├── auth/ password, session, RBAC, OIDC
│ ├── agentenroll/ REST enroll (signs CSRs)
│ ├── agentgw/ gRPC, registry, log broker, terminal, connectors
│ ├── pki/ CA + server cert + CSR signing
│ ├── jobs/, runs/, servers/, secrets/, notify/, connectors/
├── agent/
│ └── internal/
│ ├── enroll/, mtls/, store/, transport/
│ ├── scheduler/ timezone-aware local cron
│ ├── executor/ timeout + log capture
│ ├── connectors/ nginx, systemd, docker, pm2
│ ├── terminal/ PTY sessions
│ └── runtime/ top-level loop
├── web/ Next.js 16, basePath /app
└── cli/ cc