|
| 1 | +# terranix and flake modules |
| 2 | + |
| 3 | +[flake-parts][flake-parts] is a framework for Nix flakes built on the module |
| 4 | +system. As flake.parts puts it: |
| 5 | + |
| 6 | +> flakes are configuration, and the module system lets you refactor that configuration |
| 7 | +> into reusable pieces — reducing the proliferation of custom Nix glue code. |
| 8 | +
|
| 9 | +terranix ships a [flake-module][flake-module] that plugs into flake-parts. It |
| 10 | +gives you a declarative, options-based way to use terranix instead of calling |
| 11 | +`lib.terranixConfiguration` manually and wiring up your own flake outputs. |
| 12 | + |
| 13 | +[flake-parts]: https://flake.parts |
| 14 | +[flake-module]: https://github.com/terranix/terranix/blob/main/flake-module.nix |
| 15 | + |
| 16 | +## Before and after |
| 17 | + |
| 18 | +Without the flake-module, you call `lib.terranixConfiguration` yourself and |
| 19 | +manually assemble `packages`, `apps`, and `devShells`. The [Getting started |
| 20 | +with flakes](./getting-started-with-flakes.md) page shows what this looks like. |
| 21 | + |
| 22 | +With the flake-module, you declare `terranixConfigurations` and everything else |
| 23 | +is generated for you: |
| 24 | + |
| 25 | +```nix |
| 26 | +# flake.nix |
| 27 | +{ |
| 28 | + inputs = { |
| 29 | + nixpkgs.url = "github:nixos/nixpkgs"; |
| 30 | + terranix.url = "github:terranix/terranix"; |
| 31 | + terranix.inputs.nixpkgs.follows = "nixpkgs"; |
| 32 | + flake-parts.url = "github:hercules-ci/flake-parts"; |
| 33 | + flake-parts.inputs.nixpkgs-lib.follows = "nixpkgs"; |
| 34 | + }; |
| 35 | +
|
| 36 | + outputs = inputs@{ flake-parts, ... }: |
| 37 | + flake-parts.lib.mkFlake { inherit inputs; } { |
| 38 | + imports = [ inputs.terranix.flakeModules.default ]; |
| 39 | + systems = [ "x86_64-linux" ]; |
| 40 | +
|
| 41 | + perSystem = { pkgs, ... }: { |
| 42 | + terranix.terranixConfigurations.myproject = { |
| 43 | + modules = [ ./config.nix ]; |
| 44 | + }; |
| 45 | + }; |
| 46 | + }; |
| 47 | +} |
| 48 | +``` |
| 49 | + |
| 50 | +This single declaration auto-generates `packages`, `apps`, and `devShells` for |
| 51 | +each configuration. |
| 52 | + |
| 53 | +## What you get |
| 54 | + |
| 55 | +### packages |
| 56 | + |
| 57 | +Each `terranixConfigurations.<name>` becomes a package. The package is an |
| 58 | +`apply` script that runs `terraform init && terraform apply`. |
| 59 | + |
| 60 | +```shell |
| 61 | +nix run .#myproject |
| 62 | +``` |
| 63 | + |
| 64 | +### Passthru scripts |
| 65 | + |
| 66 | +The apply derivation carries `init`, `plan`, `apply`, and `destroy` as passthru |
| 67 | +attributes. This means you can run each command directly: |
| 68 | + |
| 69 | +```shell |
| 70 | +nix run .#myproject # apply |
| 71 | +nix run .#myproject.plan # plan |
| 72 | +nix run .#myproject.destroy # destroy |
| 73 | +nix run .#myproject.init # init only |
| 74 | +``` |
| 75 | + |
| 76 | +### devShells |
| 77 | + |
| 78 | +Run `nix develop .#myproject` to get an interactive shell with `apply`, `plan`, |
| 79 | +`destroy`, `init`, and the terraform/opentofu wrapper all on your `PATH`. |
| 80 | + |
| 81 | +```shell |
| 82 | +$ nix develop .#myproject |
| 83 | +$ plan |
| 84 | +$ apply |
| 85 | +$ destroy |
| 86 | +``` |
| 87 | + |
| 88 | +Set `terranix.exportDevShells = false` if you don't want these. |
| 89 | + |
| 90 | +### Terraform/OpenTofu wrapper |
| 91 | + |
| 92 | +Each script automatically creates the working directory, symlinks the generated |
| 93 | +`config.tf.json`, and runs the appropriate terraform commands. |
| 94 | + |
| 95 | +See [Customizing the Terraform binary](terraform-wrapper.md) for how to use |
| 96 | +OpenTofu, bundle provider plugins, or inject secrets. |
| 97 | + |
| 98 | +## Configuration options |
| 99 | + |
| 100 | +Each entry under `terranix.terranixConfigurations` accepts: |
| 101 | + |
| 102 | +| Option | Description | |
| 103 | +|---|---| |
| 104 | +| `modules` | List of terranix modules to evaluate | |
| 105 | +| `extraArgs` | Extra arguments passed to module evaluation (as `specialArgs`) | |
| 106 | +| `workdir` | Working directory for terraform state (defaults to the configuration name) | |
| 107 | +| `terraformWrapper.package` | Terraform or OpenTofu package (default: `pkgs.terraform`) | |
| 108 | +| `terraformWrapper.extraRuntimeInputs` | Additional packages available during terraform runs | |
| 109 | +| `terraformWrapper.prefixText` | Shell commands to run before each terraform invocation | |
| 110 | +| `terraformWrapper.suffixText` | Shell commands to run after each terraform invocation | |
| 111 | + |
| 112 | +## Multiple configurations |
| 113 | + |
| 114 | +You can define more than one configuration in the same flake. Each gets its own |
| 115 | +package, scripts, and devShell: |
| 116 | + |
| 117 | +```nix |
| 118 | +perSystem = { pkgs, ... }: { |
| 119 | + terranix.terranixConfigurations.staging = { |
| 120 | + modules = [ ./staging.nix ]; |
| 121 | + }; |
| 122 | + terranix.terranixConfigurations.production = { |
| 123 | + modules = [ ./production.nix ]; |
| 124 | + terraformWrapper.package = pkgs.opentofu; |
| 125 | + }; |
| 126 | +}; |
| 127 | +``` |
| 128 | + |
| 129 | +```shell |
| 130 | +nix run .#staging # apply staging |
| 131 | +nix run .#production.plan # plan production |
| 132 | +nix develop .#staging # interactive shell for staging |
| 133 | +``` |
0 commit comments