nx-terraform
v0.7.2
Published
An [Nx](https://nx.dev) plugin for managing Terraform projects within an Nx monorepo. This plugin provides generators, automatic project discovery, and inferred tasks for Terraform infrastructure-as-code projects.
Readme
nx-terraform
An Nx plugin for managing Terraform projects within an Nx monorepo. This plugin provides generators, automatic project discovery, and inferred tasks for Terraform infrastructure-as-code projects.
Overview
The nx-terraform plugin enables you to manage Terraform projects alongside your other code in an Nx monorepo. It provides:
- Automatic Project Discovery: Automatically discovers Terraform projects based on
main.tffiles - Inferred Tasks: Automatically creates Terraform targets (init, plan, apply, destroy, validate, fmt, output)
- Generators: Scaffold Terraform backend projects and modules
- Target Dependencies: Smart dependency management between Terraform projects
- Caching: Intelligent caching for safe operations (fmt, validate)
Installation
For New Workspaces
Create a new workspace with Terraform support:
npx create-nx-terraform-app my-workspaceThis creates a new Nx workspace with the nx-terraform plugin already configured.
For Existing Workspaces
Install the plugin in your existing Nx workspace:
nx add nx-terraformThis will:
- Add
nx-terraformas a dependency - Register the plugin in
nx.json - Enable automatic Terraform project discovery
Quick Start
Initialize the plugin (if not using
create-nx-terraform-app):nx g nx-terraform:initCreate a Terraform backend project:
nx g nx-terraform:terraform-backend my-backend --backendType=aws-s3Apply the backend (to create the state storage infrastructure):
nx run my-backend:terraform-applyCreate a Terraform module:
nx g nx-terraform:terraform-module my-infra \ --backendProject=my-backendUse Terraform targets:
nx run my-infra:terraform-init nx run my-infra:terraform-plan nx run my-infra:terraform-apply
Features
Automatic Project Discovery
The plugin automatically discovers Terraform projects by looking for main.tf files in your workspace. Projects are detected based on:
- Presence of
main.tf: Required for discovery - Project configuration: Must have
project.jsonin the same directory - Project type: Determined by
projectTypeandmetadatainproject.json
Inferred Tasks
The plugin automatically creates these targets for each Terraform project:
- terraform-init: Initialize Terraform workspace
- terraform-plan: Create execution plan
- terraform-apply: Apply changes to infrastructure
- terraform-destroy: Destroy infrastructure
- terraform-validate: Validate Terraform configuration
- terraform-fmt: Format Terraform code
- terraform-output: Show Terraform outputs
Project Types
The plugin supports three types of Terraform projects:
Backend Projects (
applicationwithoutbackendProjectmetadata):- Manage remote state infrastructure (e.g., S3 bucket, DynamoDB table)
- Generate
backend.configfiles - Full target set with caching enabled
Stateful Projects (
applicationwithbackendProjectmetadata):- Infrastructure projects that use remote state
- Reference backend project via
metadata['nx-terraform'].backendProject - Full target set (no caching for init/plan due to state)
Module Projects (
library):- Reusable Terraform modules
- No state management
- Stub targets (modules don't have state)
Smart Dependencies
The plugin automatically manages dependencies between Terraform projects using the createDependencies API. This creates a project dependency graph that ensures proper execution order.
Automatic Dependency Detection
The plugin automatically detects and creates dependencies in two ways:
Backend Project Dependencies: Projects with
metadata['nx-terraform'].backendProjectin theirproject.jsonautomatically depend on their backend project. This ensures backend projects are applied before stateful projects initialize.Module Reference Dependencies: The plugin analyzes
.tffiles to detect module references using local paths (e.g.,source = "../../packages/networking"). When a module block references another Terraform project, a dependency is automatically created.
How Module Detection Works:
- Scans
.tffiles formoduleblocks - Extracts
sourceattributes that use local paths (./or../) - Matches the last path segment to project names in the workspace
- Creates static dependencies from the referencing project to the referenced project
Example:
# In packages/web-app/main.tf
module "networking" {
source = "../../packages/networking"
# ... module configuration
}This automatically creates a dependency: web-app → networking
Target Dependencies
In addition to project dependencies, targets have their own dependencies:
- Backend first:
terraform-initdepends on^terraform-apply(backend must be applied first) - Init before operations:
terraform-plan,terraform-apply, andterraform-validaterequireterraform-init - Plan before apply:
terraform-applydepends onterraform-plan
Caching
Intelligent caching for safe operations:
- Cached:
terraform-fmt,terraform-validate(when safe) - Non-cached:
terraform-init,terraform-plan,terraform-apply(state-dependent)
Generators
The plugin provides five generators:
init Generator
Registers the nx-terraform plugin in your workspace.
nx g nx-terraform:initDocumentation: packages/nx-terraform/src/generators/init/README.md
terraform-backend Generator
Creates a Terraform backend project for managing remote state.
nx g nx-terraform:terraform-backend my-backend --backendType=aws-s3Options:
name: Backend project name (required)backendType: 'aws-s3' or 'local' (required)bucketNamePrefix: Prefix for S3 bucket name (optional, AWS S3 only)
Documentation: packages/nx-terraform/src/generators/terraform-backend/README.md
terraform-module Generator
Creates Terraform modules (simple library or stateful application).
# Simple module (library)
nx g nx-terraform:terraform-module my-module
# Stateful module (application)
nx g nx-terraform:terraform-module my-infra \
--backendProject=my-backendOptions:
name: Module name (required)backendProject: Backend project name (optional, creates stateful module if provided). The backend type is automatically derived from the backend project's metadata.
Documentation: packages/nx-terraform/src/generators/terraform-module/README.md
preset Generator
Initializes workspace with Terraform setup (used by create-nx-terraform-app).
# With backend (creates backend + stateful module)
nx g nx-terraform:preset --projectName=terraform-setup --backendType=aws-s3
# Without backend (creates simple module only)
nx g nx-terraform:preset --projectName=terraform-setupOptions:
projectName: Workspace name (required)backendType: 'aws-s3' or 'local' (optional, if not provided only creates simple module)
Documentation: packages/nx-terraform/src/generators/preset/README.md
sync-terraform-metadata Generator
Automatically syncs Terraform project metadata based on .tf file analysis.
nx g nx-terraform:sync-terraform-metadataThis generator scans all Terraform projects and updates projectType metadata based on the presence of backend blocks in .tf files. It also updates provider.tf files with module dependency metadata. It's designed to be run as a global sync generator.
Documentation: packages/nx-terraform/src/generators/sync-terraform-metadata/README.md
Targets
Each Terraform project automatically gets these targets:
terraform-init
Initializes Terraform workspace.
nx run my-project:terraform-initDependencies: ^terraform-apply (backend must be applied first)
Sync Generators: Automatically runs sync-terraform-metadata generator before initialization to ensure project metadata is up to date
terraform-plan
Creates an execution plan.
nx run my-project:terraform-planDependencies: terraform-init
Configurations: Supports dev and prod configurations via -var-file arguments
terraform-apply
Applies changes to infrastructure.
nx run my-project:terraform-applyDependencies: terraform-plan
Configurations: Supports dev and prod configurations
terraform-destroy
Destroys infrastructure.
nx run my-project:terraform-destroyDependencies: terraform-init
terraform-validate
Validates Terraform configuration.
nx run my-project:terraform-validateDependencies: terraform-init
Caching: Enabled (safe operation)
terraform-fmt
Formats Terraform code.
nx run my-project:terraform-fmtCaching: Enabled (safe operation)
terraform-output
Shows Terraform outputs.
nx run my-project:terraform-outputDependencies: terraform-init
Project Structure
Terraform projects should follow this structure:
packages/
└── my-terraform-project/
├── project.json # Nx project configuration
├── main.tf # Required for discovery
├── backend.tf # Backend configuration (stateful projects)
├── provider.tf # Provider requirements
├── variables.tf # Input variables
├── outputs.tf # Output values
├── tfvars/
│ ├── dev.tfvars # Dev environment variables
│ └── prod.tfvars # Prod environment variables
└── backend.config # Generated backend config (backend projects)Project Configuration
For stateful projects, configure metadata['nx-terraform'].backendProject:
{
"root": "packages/my-infra",
"projectType": "application",
"metadata": {
"nx-terraform": {
"backendProject": "my-backend"
}
}
}Configuration
Backend Types
The plugin supports two backend types:
AWS S3 Backend
Production-ready remote state storage using AWS S3:
nx g nx-terraform:terraform-backend my-backend --backendType=aws-s3Features:
- Versioning enabled
- Object lock for state protection
- Dynamic bucket naming
- Region detection
Local Backend
Local state files for development:
nx g nx-terraform:terraform-backend my-backend --backendType=localUse Cases:
- Development and testing
- Single-user scenarios
- Ephemeral environments
Environment Variables
Terraform projects support environment-specific variables via tfvars files:
tfvars/dev.tfvars- Development environmenttfvars/prod.tfvars- Production environment
Targets automatically use the appropriate -var-file argument based on configuration:
# Uses tfvars/dev.tfvars
nx run my-project:terraform-plan --configuration=dev
# Uses tfvars/prod.tfvars
nx run my-project:terraform-plan --configuration=prodExamples
Complete Workflow
# 1. Create new workspace (creates terraform-setup backend and terraform-infra module)
npx create-nx-terraform-app my-workspace
# 2. Apply backend (from workspace creation)
cd my-workspace
nx run terraform-setup:terraform-apply
# 3. Plan and apply infrastructure module (already created by preset)
nx run terraform-infra:terraform-init
nx run terraform-infra:terraform-plan --configuration=dev
nx run terraform-infra:terraform-apply --configuration=dev
# 4. (Optional) Create additional infrastructure modules
nx g nx-terraform:terraform-module web-infra \
--backendProject=terraform-setupMultiple Environments
# Create dev environment
nx g nx-terraform:terraform-module dev-infra \
--backendProject=terraform-setup
# Create prod environment
nx g nx-terraform:terraform-module prod-infra \
--backendProject=terraform-setup
# Deploy to dev
nx run dev-infra:terraform-plan --configuration=dev
nx run dev-infra:terraform-apply --configuration=dev
# Deploy to prod
nx run prod-infra:terraform-plan --configuration=prod
nx run prod-infra:terraform-apply --configuration=prodReusable Modules with Automatic Dependencies
# Create reusable networking module
nx g nx-terraform:terraform-module networking
# Create web app that uses the networking module
nx g nx-terraform:terraform-module web-app \
--backendProject=terraform-setupThen reference the module in your Terraform code:
# In packages/web-app/main.tf
module "networking" {
source = "../../packages/networking"
vpc_cidr = "10.0.0.0/16"
}Automatic Dependency Detection: The plugin automatically detects this module reference and creates a project dependency (web-app → networking). When you run nx graph, you'll see the dependency visualized. This ensures networking is built/validated before web-app.
Project Discovery
The plugin automatically discovers Terraform projects using:
- Pattern:
**/main.tf(looks formain.tffiles recursively) - Requirement: Projects must have
project.jsonin the same directory - Type Detection: Based on
projectTypeandmetadata['nx-terraform'].backendProject
Projects are discovered on workspace load, so new projects are automatically available without restarting Nx.
Caching Strategy
Caching behavior varies by project type:
Backend Projects (caching enabled)
- terraform-init: Cached (backend projects don't depend on external state)
- terraform-plan: Cached
- terraform-apply: Cached
- terraform-fmt: Cached (code formatting is deterministic)
- terraform-validate: Cached (validation results can be cached when inputs haven't changed)
- terraform-destroy: Not cached
- terraform-output: Not cached
Stateful Projects (caching disabled for state-dependent operations)
- terraform-init: Not cached (state-dependent, requires backend access)
- terraform-plan: Not cached (state-dependent, shows infrastructure changes)
- terraform-apply: Not cached (state-dependent, modifies infrastructure)
- terraform-fmt: Cached (code formatting is deterministic)
- terraform-validate: Cached (validation results can be cached when inputs haven't changed)
- terraform-destroy: Not cached
- terraform-output: Not cached
Module Projects (library)
- terraform-fmt: Cached
- terraform-validate: Cached
- terraform-apply: Not cached (though modules typically don't use apply)
- All other targets are stubs (cached but no-op)
Cache inputs include:
- All
.tfand.tfvarsfiles - Relevant environment variables
- Terraform version
- Provider and backend configuration files
Compatibility
- Nx: v22.0.2 or compatible
- Terraform: Any version (uses Terraform CLI)
- Node.js: v18+ recommended
Documentation
Comprehensive documentation is available for each component:
Generators:
init- Plugin initializationterraform-backend- Backend project creationterraform-module- Module creationpreset- Workspace presetsync-terraform-metadata- Metadata synchronization
Workspace Creation:
create-nx-terraform-app- CLI tool for workspace creation
Contributing
Contributions are welcome! Please see the repository for contribution guidelines.
License
MIT
Repository
https://github.com/alexpialetski/nx-terraform
