Generate Terranix NixOS modules from Terraform provider schemas.
Terraform providers define hundreds or thousands of resources, each with a typed schema. terranix-codegen reads those schemas and produces NixOS module files that give you type-checked options for every resource, data source, and provider config block -- so you don't have to write them by hand.
terranix-codegen uses OpenTofu by default. Pass -t terraform to use HashiCorp Terraform instead.
# Generate for one or more providers (fetches schemas via tofu automatically)
terranix-codegen generate -p aws -o ./providers
terranix-codegen generate -p hashicorp/aws:5.0.0 -p google -o ./providers
# Use Terraform instead of OpenTofu
terranix-codegen generate -p aws -t terraform -o ./providers# From file
terranix-codegen generate -i schema.json -o ./providers
# From stdin
tofu providers schema -json | terranix-codegen generate -o ./providers# Pretty-print to terminal (colorized)
terranix-codegen show -p aws
# Dump as JSON
terranix-codegen schema -p aws --pretty > schema.json# config.nix
{
imports = [ ./providers/registry.terraform.io/hashicorp/aws ];
resource.aws_instance.web = {
ami = "ami-123456";
instance_type = "t2.micro";
};
}providers/
├── default.nix
└── registry.terraform.io/
└── hashicorp/
└── aws/
├── default.nix
├── provider.nix
├── resources/
│ ├── default.nix
│ ├── instance.nix
│ ├── vpc.nix
│ └── ...
└── data-sources/
├── default.nix
├── ami.nix
└── ...
Each default.nix imports its siblings, so importing the provider directory pulls in everything.
- Parse provider specs --
hashicorp/aws:5.0.0,aws, etc. Namespace and version are optional. - Run tofu/terraform -- generates a minimal
.tfconfig, runsinitandproviders schema -jsonin a temp directory. - Parse the JSON schema -- Terraform's type system (go-cty) is mapped to Haskell ADTs covering all type constructors (
string,number,bool,list(T),set(T),map(T),object({...}),tuple([...]),dynamic) and all 5 block nesting modes (single,group,list,set,map). - Map types to Nix --
CtyStringbecomestypes.str,CtyList CtyNumberbecomestypes.listOf types.number,CtyObjectbecomestypes.submodule, etc. Terraform tuples map to a customtypes.tupleOfthat validates length and per-position types. - Build
mkOptioncalls -- each schema attribute becomes anmkOptionwith the mapped type, a default value (nullfor optional/computed attributes), description text, and metadata annotations (deprecated, sensitive, write-only, computed/read-only). - Assemble modules -- resources get
options.resource.<type>, data sources getoptions.data.<type>, provider config getsoptions.provider.<name>. Nested blocks are handled recursively. - Write files -- one
.nixfile per resource/data source, plusdefault.nixfiles for imports, organized by provider.
All Nix code generation goes through hnix's AST and pretty-printer rather than string templates.
Requires Nix with flakes.
# Enter dev shell
nix develop
# Build
cabal build
# Run tests
cabal test --enable-tests
# Or build via Nix
nix build--providers-fileflag (load provider specs from a JSON file)- Documentation generation (mdBook output for generated modules)
- Resource/provider filtering
- Pre-built module sets for common providers