8 releases
Uses new Rust 2024
| new 0.4.12 | Jan 26, 2026 |
|---|---|
| 0.4.11 | Dec 30, 2025 |
| 0.4.2 | Nov 22, 2025 |
#1548 in Command line utilities
375KB
10K
SLoC
Greentic Deployer
greentic-deployer is a CLI and library that builds cloud-agnostic deployment plans for Greentic packs and then runs provider-specific deployment packs (kind deployment) to materialise the required IaC/artifacts for AWS, Azure, GCP, local, K8s, or any other target.
Concepts
- Application packs (kind
applicationormixed) describe flows, components, tools, secrets, and tenant bindings.greentic-deployerintrospects them to understand runners, messaging, channels, secrets, OAuth, and telemetry requirements. - DeploymentPlan is a provider-agnostic model (
greentic-types::DeploymentPlan) that captures messaging topology, runner services, channel ingress, secrets, OAuth redirect URLs, and telemetry hooks. - Deployment packs (kind
deployment) supply provider-specific deployment flows. Each flow is atype: eventsflow made of deployment components (supports: ["events"],world: "greentic:deploy-plan@1.0.0") that can read the plan viaget-deployment-plan()and emit IaC/templates when the host grantshost.iac.write_templates. - Providers / strategies are a mapping (
provider,strategy) →(deployment_pack_id, deploy_flow_id); e.g.("aws","serverless") -> ("greentic.deploy.aws","deploy_aws_serverless").greentic-deployerchooses the mapping for the requested--provider/--strategy, loads that deployment pack, and executes it viagreentic-runner. - Legacy Rust backends exist for AWS/Azure/GCP; Local/K8s currently require deployment packs + a registered executor and will return
DeploymentPackUnsupportedif no executor is present.
Building
cargo build -p greentic-deployer
Install
From crates.io:
cargo install greentic-deployer
Prefer prebuilt artifacts?
cargo install cargo-binstall
cargo binstall greentic-deployer
cargo binstall greentic-deployer downloads release tarballs for your platform so you don’t have to build from source.
CLI
greentic-deployer <plan|apply|destroy> --provider <local|aws|azure|gcp|k8s> \
--tenant <tenant-id> --environment <env> --pack <path> \
[--yes] [--preview] [--dry-run] [--iac-tool <tf|terraform|tofu|opentofu>] \
[--output <text|json|yaml>]
Examples:
- Plan an AWS deployment:
greentic-deployer plan --provider aws --tenant acme --environment staging --pack examples/acme-pack
- Apply the plan once reviewed:
```bash
greentic-deployer apply --provider aws --tenant acme --environment staging --pack examples/acme-pack --yes
- Destroy resources when you no longer need them:
greentic-deployer destroy --provider aws --tenant acme --environment staging --pack examples/acme-pack - Plan locally (requires a deployment pack + executor for local targets):
greentic-deployer plan --provider local --tenant acme --environment dev --pack examples/acme-pack --output json - Resolve packs from a distributor/registry instead of the filesystem:
greentic-deployer plan \ --provider aws \ --tenant acme \ --environment staging \ --pack-id dev.greentic.sample \ --pack-version 0.1.0 \ --pack-digest sha256:deadbeef \ --distributor-url https://distributor.example.com \ --distributor-token $DISTRIBUTOR_TOKEN
Plans and provider artifacts are written to deploy/<provider>/<tenant>/<environment>/ for inspection.
Plan output also lists component role/profile mappings per target; use --output json or --output yaml for machine-readable summaries.
For Local/K8s targets, wire in a deployment pack + executor (or extend the provider mapping) because legacy shims are only available for AWS/Azure/GCP.
Configuration
- Configuration is resolved via
greentic-configwith precedenceCLI > env > project (.greentic/config.toml) > user (~/.config/greentic/config.toml) > defaults. If you pass--config <path>, that file replaces project discovery; precedence becomesCLI > env > explicit file > user > defaults. Use--config <path>for an explicit file and--explain-config/--explain-config-jsonto print the resolved config/provenance. deployer.base_domainin config controls the domain used when emitting OAuth redirect URLs and channel ingress; defaults todeploy.greentic.aivia greentic-config.- OTLP tracing reads the endpoint from config;
OTEL_EXPORTER_OTLP_ENDPOINTremains a fallback. - IaC tool selection comes from
--iac-tool(Terraform/OpenTofu) or PATH auto-detection (prefers tofu). - When
connectionis set toOfflinein config, remote pack/distributor access is blocked unless--allow-remote-in-offlineis provided.
Secrets & OAuth
- Secret requirements are pulled from pack metadata (
secret_requirements) and surfaced in plans. Apply/destroy preflight each required secret via the secrets-store and fail fast with the missing key list plus a remediation hint (greentic-secrets init --pack <pack>). No secret values are logged. greentic-deployerresolves secrets using the runtime tenant/environment scope; apply/destroy fail if the secrets-store does not contain the required entries.- OAuth clients use
greentic-oauth’sProviderIdidentifiers (e.g.google,microsoft,github) so downstream tooling can reuse the same descriptors when wiring the broker, and redirect URLs continue to follow thehttps://{domain}/oauth/{provider}/callback/{tenant}/{environment}pattern.
-## Telemetry & Provider Artifacts
- Telemetry is instrumented via
greentic-telemetry, which publishes OTLP spans for eachplan,apply, ordestroyaction and injects a task-localTelemetryCtxcapturing tenant/provider/session keys. - Provider artifacts now embed the telemetry endpoint and context in the generated shell/HashiCorp/Deployment Manager snippets (for example, Terraform output includes
OTEL_EXPORTER_OTLP_ENDPOINT, Azure Bicep adds the value under containerenv, and GCP config adds the annotation metadata), so every generated service inherits the tenant context. - Secrets, OAuth redirects, and binding hints are surfaced directly inside the provider outputs so you can see which vault entries and redirect URLs will be consumed up front.
- OAuth clients are inferred from channel requirements. Each redirect URL follows the pattern
https://{domain}/oauth/{provider}/callback/{tenant}/{environment}.
Runner & Messaging Insights
- The deployment plan includes binding hints per runner (e.g. NATS connectivity, channel ingress) plus the WASI world name for every component so deployment packs know what to host.
MessagingPlancaptures the JetStream-enabled cluster topology and subjects that deployment packs may reference when producing IaC snippets.
Example packs
examples/acme-pack
- Minimal single-flow application pack with two secrets and two OAuth clients surfaced via annotations.
- Component manifests (
components/qa/process/manifest.json) drive secret discovery so deployment packs render the right vault references. - Running the CLI drops
master.tf,variables.tf, andplan.jsonunderdeploy/<provider>/acme/staging/. annotations.greentic.deploymentsets the preferred deployment strategy (e.g."iac-only"); when omitted, the CLI--strategyflag is used.
examples/acme-plus-pack
- Multi-flow application pack with two components (
support.automator,ops.router), four secrets, two channel connectors, and explicit messaging subjects. - Exercising this pack produces richer IaC under
deploy/<provider>/acmeplus/staging/. - Also declares
greentic.deployment.strategy = "iac-only"so downstream tooling knows which deployment pack/flow to target by default.
Both packs log telemetry via greentic-telemetry so plan/apply/destroy traces show up in OTLP backends.
Terraform & OpenTofu
- Provider artifacts live under
deploy/<provider>/<tenant>/<environment>/and the CLI runs the selected IaC tool inside that directory. --iac-toolorGREENTIC_IAC_TOOLaccepttf|terraform|tofu|opentofu; when unset the deployer preferstofuthen falls back toterraform.- Apply runs
init,plan,apply plan.tfplan; destroy runsinit,destroy.--dry-runprints the command list without executing anything.
Re-running provider artifacts
Once artifacts exist and secrets are stored you can re-run them manually:
- Inspect
apply-manifest.json/destroy-manifest.jsonto confirm secret paths and OAuth redirect URLs. - AWS:
cd deploy/aws/<tenant>/<environment>and run the recorded Terraform/OpenTofu commands (master.tf,variables.tf,plan.json). - Azure:
master.bicepplusparameters.jsonfeedaz deployment group create .... - GCP:
master.yamlplusparameters.yamlfeedgcloud deployment-manager deployments create .... --dry-runor--previewshow the IaC shell commands without touching cloud resources.
Try the sample packs
- Minimal pack:
cargo run -p greentic-deployer -- plan --provider aws --tenant acme --environment staging --pack examples/acme-pack - Inspect
deploy/aws/acme/staging/(and matchingazure/gcp) for:master.tf,variables.tf,plan.json(AWS).master.bicep,parameters.json,plan.json(Azure).master.yaml,parameters.yaml,plan.json(GCP).
apply/destroywrite manifests listing secrets, OAuth redirects, and telemetry attributes, so you can double-check before running IaC directly.- Repeat with the larger pack (same deployment pack, richer plan):
cargo run -p greentic-deployer -- plan --provider aws --tenant acmeplus --environment staging --pack examples/acme-plus-pack
CI smoke test
scripts/ci-smoke.shiterates over providers (aws/azure/gcp), actions (apply/destroy), and both packs in--dry-runmode to guarantee IaC command generation works. Local/K8s are not covered by the legacy shims and require a deployment pack executor../ci/local_check.shis the local equivalent run before pushing (fmt, clippy, tests, docs, and the smoke script).
Repo settings
- Enable GitHub’s “Allow auto-merge” so Dependabot PRs can merge after required checks pass; set required status checks via branch protection as needed.
Sample IaC output / deployment packs
- Deployment packs such as
greentic.deploy.awsorgreentic.deploy.genericconsume the plan viagreentic:deploy-plan@1.0.0and emit IaC underdeploy/<provider>/<tenant>/<environment>/. deploy/aws/acmeplus/staging/master.tfhighlights the ECS setup generated by the AWS deployment pack.deploy/azure/acmeplus/staging/master.bicepincludes container apps and secret bindings generated by the Azure deployment pack.deploy/gcp/acmeplus/staging/master.yamlexpresses Deployment Manager resources with inline Secret Manager references from the GCP deployment pack.- See
docs/provider-visual-guide.md(and the SVG mocks underdocs/images/) for diagrams + screenshot tips. - See
docs/platform_bootstrap.mdfor platform bootstrap/installer architecture and manifestbootstrapblock conventions. - CLI scaffold includes
platform install|upgrade|statuscommands (currently reporting metadata only) to support bootstrap flows; help text notes offline-first/bootstrap-state intent and verification flags.
Adding new deployment targets
- Author a deployment pack (
kind: deployment) withtype: eventsflows made of deployment components (supports: ["events"],world: "greentic:deploy-plan@1.0.0",host.iac.write_templates = true). - Publish that pack (e.g.
greentic.deploy.mycloudwith flowdeploy_mycloud_iac). - Update the provider/strategy mapping so
("mycloud","iac") -> ("greentic.deploy.mycloud","deploy_mycloud_iac"). greentic-deployerremains provider-agnostic: it loads the application pack, builds theDeploymentPlan, selects the deployment pack based on--provider/--strategy, and delegates IaC generation to the flow viagreentic-runner.- Hosts (runner/control planes) should register their executor via:
Registered executors receive the resolveduse std::sync::Arc; use greentic_deployer::deployment::{self, DeploymentDispatch, DeploymentExecutor}; struct RunnerExecutor; #[async_trait::async_trait] impl DeploymentExecutor for RunnerExecutor { async fn execute( &self, config: &greentic_deployer::DeployerConfig, plan: &greentic_deployer::plan::PlanContext, dispatch: &DeploymentDispatch, ) -> greentic_deployer::Result<()> { // Call greentic-runner with (dispatch.pack_id, dispatch.flow_id) + plan JSON. Ok(()) } } deployment::set_deployment_executor(Arc::new(RunnerExecutor));(pack_id, flow_id)and can invokegreentic-runnerusing the shared bindings fromgreentic-interfaces-host. If no executor is registered the legacy Rust shims run as a fallback.
Dependencies
~53–80MB
~1.5M SLoC