Skip to content

devx/sprout

Repository files navigation

openCenter Sprout

Sprout is an Apache-2.0, API-first bare-metal lifecycle platform for discovering, commissioning, provisioning, operating, and retiring physical infrastructure across one or more sites.

Status

This repository now contains the first headless MVP implementation:

  • sprout-api: Go HTTP control plane with OIDC auth, audit, workflows, and PostgreSQL persistence
  • sprout-site-agent: Go site-local worker with NATS assignment handling, iPXE/autoinstall rendering, and Redfish-first power-cycle support
  • sprout-cli: thin operator CLI for the supported MVP workflows

Why Sprout Exists

Existing bare-metal platforms usually force one of three tradeoffs:

  • restrictive or incompatible licensing
  • tightly coupled control planes with high operational complexity
  • weak separation between core lifecycle logic and site-local execution

Sprout is intended to take a different path:

  • Apache-2.0 licensing from day one
  • a small Go control-plane core with clean module boundaries
  • site-local agents for hardware-facing work
  • API and CLI first, with UI following later
  • optional integrations for metadata, secrets, and identity instead of baking those systems into the core

Product Principles

  • API-first: every operator workflow must be available through a stable public API.
  • Small core: inventory, lifecycle, workflow, audit, and policy stay in the control plane; hardware side effects stay behind adapters and agents.
  • Site-local execution: boot services, metadata delivery, BMC actions, and artifact caching run near the hardware when possible.
  • Business-friendly reuse: permissive licensing and integration boundaries matter as much as feature depth.
  • Security by default: human auth, workload identity, auditability, and external secrets integration are first-class design requirements.

Target Architecture

Sprout is designed around these core elements:

  • sprout-api: public control-plane API
  • sprout-site-agent: site-local execution agent
  • PostgreSQL: system of record for inventory, workflow, and audit state
  • NATS JetStream: asynchronous workflow and site-agent messaging
  • embedded netboot, node metadata, and Redfish-backed Day 2 execution inside the site agent for the MVP

Additional details live in:

Planned Scope

The initial product focus is deliberately narrow:

  • hardware inventory and lifecycle state
  • commissioning and provisioning workflows
  • site registration and delegated execution
  • audited operator actions
  • a limited Day 2 surface for safe operational tasks

Sprout explicitly avoids becoming:

  • a general-purpose CMDB
  • a full content or patch management stack
  • a hypervisor or VM lifecycle platform
  • a network fabric orchestration system
  • an OpenStack distribution

Repository Layout

api/                    OpenAPI contracts
cmd/                    API, agent, and CLI entrypoints
db/migrations/          PostgreSQL schema migrations
deploy/                 local development assets such as Keycloak realm import
docs/product/           product intent, requirements, scope, use cases
docs/architecture/      target architecture, security, deployment, ADRs
docs/plans/             MVP, phases, risks, team model
internal/               control-plane, agent, store, messaging, and CLI packages
README.md               project overview
SECURITY.md             vulnerability reporting and security baseline
CONTRIBUTING.md         contribution workflow
ROADMAP.md              delivery outlook

Getting Started

  1. Start the local dependencies:
make bootstrap
make dev-up
  1. Copy .env.example to .env and set SPROUT_SITE_ID once you have created a site.

  2. Run the API:

make run-api
  1. Use Keycloak on http://localhost:8082, obtain a token for the sprout-api client, and export it as SPROUT_API_TOKEN.

  2. Create a site with the CLI:

go run ./cmd/sprout-cli sites create --name "Lab A" --slug lab-a
  1. Start the site agent after setting SPROUT_SITE_ID:
make run-agent
  1. Create a provisioning network and a machine with a PXE-capable interface:
go run ./cmd/sprout-cli networks create --site-id <site-id> --name provisioning --cidr 192.0.2.0/24 --gateway 192.0.2.1 --dns 1.1.1.1,8.8.8.8 --range-start 192.0.2.10 --range-end 192.0.2.50 --purpose provisioning
go run ./cmd/sprout-cli machines create --site-id <site-id> --hostname node-01 --architecture x86_64 --interface id=iface-1,name=eth0,macAddress=52:54:00:12:34:56,pxeEnabled=true,networkName=provisioning
  1. Use the CLI for machine lifecycle and capacity actions:
go run ./cmd/sprout-cli artifacts create --ref ubuntu-cache --name "Ubuntu Cache" --backend filesystem --base-url http://localhost:8081/artifacts --prefix ubuntu/24.04
go run ./cmd/sprout-cli images create --ref ubuntu-24.04 --name "Ubuntu 24.04" --architecture x86_64 --artifact-ref ubuntu-cache --kernel-path vmlinuz --initrd-path initrd
go run ./cmd/sprout-cli profiles create --ref default --name "Default" --cloud-config-template '#cloud-config
hostname: {{ hostname }}'
go run ./cmd/sprout-cli machines commission <machine-id> --reason "commission for adoption"
go run ./cmd/sprout-cli machines provision <machine-id> --image-ref ubuntu-24.04 --profile-ref default --network-id <network-id>
go run ./cmd/sprout-cli ip-allocations list --machine-id <machine-id>
go run ./cmd/sprout-cli machines allocate --site-id <site-id> --count 2 --label role=worker --architecture x86_64 --min-memory-mib 16384 --min-disk-bytes 536870912000
go run ./cmd/sprout-cli machines image <machine-id> --media-url https://cache.example.com/ubuntu.iso --boot-source virtual-media
go run ./cmd/sprout-cli machines power-on <machine-id> --reason "restore service"
go run ./cmd/sprout-cli machines power-off <machine-id> --reason "maintenance window"
go run ./cmd/sprout-cli machines boot-source <machine-id> --boot-source pxe --reason "next boot from network"
go run ./cmd/sprout-cli day2-actions list
go run ./cmd/sprout-cli approvals create --machine-id <machine-id> --action release --decision approved --reason "approved maintenance"
go run ./cmd/sprout-cli machines reboot <machine-id> --approval-id <approval-id> --reason "restart after patch"
go run ./cmd/sprout-cli machines remote-task <machine-id> --approval-id <approval-id> --command uptime --reason "capture host state"
go run ./cmd/sprout-cli action-executions list --machine-id <machine-id>
go run ./cmd/sprout-cli action-executions evidence <execution-id>
go run ./cmd/sprout-cli policy-decisions list --machine-id <machine-id>
go run ./cmd/sprout-cli workflows events <workflow-id>
go run ./cmd/sprout-cli sync-jobs create --site-id <site-id> --artifact-ref ubuntu-cache --mode preseed
go run ./cmd/sprout-cli sync-jobs list --site-id <site-id>
go run ./cmd/sprout-cli integration-jobs create --name lab-a-export --site-id <site-id> --kind metadata-export --provider webhook --endpoint https://ops.example.com/hooks/sprout
go run ./cmd/sprout-cli integration-jobs run <job-id>
go run ./cmd/sprout-cli sites health <site-id>
go run ./cmd/sprout-cli discoveries list --site-id <site-id>
go run ./cmd/sprout-cli discoveries accept <discovery-id>
go run ./cmd/sprout-cli audit list

To inspect the API contract directly, see api/openapi.yaml.

Site-scoped RBAC groups can be expressed as sprout-site:<site-id>:viewer, sprout-site:<site-id>:operator, or sprout-site:<site-id>:admin.

For headless secret and transport hardening, the agent and API also accept:

  • SPROUT_VAULT_ADDRESS, SPROUT_VAULT_TOKEN, and SPROUT_SECRET_ENV_PREFIX for dev and Vault-backed secret resolution
  • SPROUT_TLS_ENABLED, SPROUT_TLS_CA_FILE, SPROUT_TLS_CERT_FILE, SPROUT_TLS_KEY_FILE, and SPROUT_WORKLOAD_TRUST_DOMAIN for optional mTLS and SPIFFE-style workload identities

Workflow assignments and artifact sync jobs are targeted to the most recent capable site agent and carry renewable lease metadata so reconnects and multi-agent sites can recover cleanly.

The API also exposes Prometheus-compatible metrics at /metrics, returns an X-Request-Id header on every response, and supports integration jobs for webhook or OpenMetadata export plus HTTP-based inventory import.

Infrastructure providers are selected per capability with SPROUT_<CAP>_PROVIDER=builtin|external. Builtin network/IPAM/allocation use PostgreSQL. Builtin DHCP and DNS use the site agent and require SPROUT_DHCP_BIND_INTERFACE, SPROUT_DHCP_BIND_ADDR, and SPROUT_DNS_BIND_ADDR. External providers use bearer-auth REST endpoints at SPROUT_<CAP>_EXTERNAL_URL, and provisioning DNS records default to SPROUT_PROVISIONING_DOMAIN=provisioning.sprout.local.

Language and Runtime Direction

Sprout is planned as:

  • Go for the control plane, site agents, and core services
  • TypeScript for a later web UI
  • Python only for narrow integration-heavy adapters where it has a clear advantage

Contributing and Security

License

Sprout is intended to be released under Apache-2.0.

About

Sprout is an Apache-2.0, API-first bare-metal lifecycle platform for discovering, commissioning, provisioning, operating, and retiring physical infrastructure across one or more sites.

Resources

License

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors