terranix

terranix is a Nix-based infrastructure-as-code tool that combines the providers of Terraform (or OpenTofu) and the lazy, functional configuration of NixOS. terranix works as an alternative to HCL by generating Terraform JSON that can then be applied using the same providers.

What does terranix look like? #

Here’s an example of how one might deploy a VPS along an A record that points to it:

terranix config.nix
let
  mkSite = { name, region }: {
    resource.digitalocean_droplet.${name} = {
      name = name;
      region = region;
      image = "ubuntu-22-04-x64";
      size = "s-1vcpu-1gb";
    };
    resource.digitalocean_record.${name} = {
      name = name;
      domain = "example.com";
      type = "A";
      value = "\${digitalocean_droplet.${name}.ipv4_address}";
    };
  };
in {
  imports = [
    (mkSite { name = "web-1"; region = "fra1"; })
    (mkSite { name = "web-2"; region = "nyc1"; })
    (mkSite { name = "web-3"; region = "sgp1"; })
  ];
}
HCL main.tf
locals {
  sites = {
    web-1 = "fra1"
    web-2 = "nyc1"
    web-3 = "sgp1"
  }
}

resource "digitalocean_droplet" "site" {
  for_each = local.sites
  name     = each.key
  region   = each.value
  image    = "ubuntu-22-04-x64"
  size     = "s-1vcpu-1gb"
}

resource "digitalocean_record" "site" {
  for_each = local.sites
  domain   = "example.com"
  type     = "A"
  name     = each.key
  value    = digitalocean_droplet.site[each.key].ipv4_address
}

Features

  • Full Nix language
    Use let-bindings, imports, conditionals, and module composition. Allow for nested structures and re-use. For a comparison, see terranix vs. HCL.
  • NixOS module system
    Type-checked configuration with sensible defaults, overrides, and reusable modules. Opt-in flake support. For a comparison, see Modules.
  • nixpkgs ecosystem
    Tap into fetchgit, fetchurl, writers, work and pin Terraform / OpenTofu versions and providers reproducibly.
  • Transcend IAC boundaries
    Combine your terranix configuration with arbitrary Nix: If you can express it with Nix, you can provision it. Conversely, if you’ve provisioned it, you can reference it elsewhere. See example.
  • Reproducible builds
    Pin Terraform / OpenTofu and every provider as Nix derivations, so the same config.nix produces an identical plan. Work across repos.
  • Multi-environment
    Generate different Terraform JSON outputs from the same module by passing env, region, or workspace arguments as plain Nix function inputs.