# Publish a Terraform Module

## Overview

Convert your existing Terraform module into a Bluebricks package in two steps: prepare locally, then publish to your organization.

## Prerequisites

* Bricks CLI installed and authenticated (`bricks login`)
* Existing Terraform module with `.tf` files

## How to publish a Terraform module

{% stepper %}
{% step %}
**Prepare your module**

Navigate to your Terraform directory and run:

```bash
cd /path/to/your-terraform-module
bricks blueprint prepare --source . --iac-type terraform
```

This creates a `bricks.json` with auto-detected variables and outputs. Your original `.tf` files remain in place.
{% endstep %}

{% step %}
**Publish to your organization**

```bash
bricks blueprint publish
```

Your module is now available to your organization.
{% endstep %}
{% endstepper %}

## What each command does

**`bricks blueprint prepare`** generates a `bricks.json` in your current directory. No files are moved or copied, and no API calls are made. Your `.tf` files stay exactly where they are.

**`bricks blueprint publish`** uploads your package to Bluebricks. Variables and outputs are auto-discovered from your `.tf` files, external module references are resolved (if `--resolve-modules` is enabled), and the package is made available to your organization.

## Working with existing modules

### Local module references

If your Terraform uses local modules:

```hcl
module "vpc" {
  source = "../networking/vpc"
}

module "subnets" {
  source = "../networking/subnets"
}
```

**Bluebricks automatically handles this** with `--resolve-modules` (enabled by default):

```bash
bricks blueprint publish --resolve-modules
```

What happens:

1. Finds all modules referenced with `../`
2. Copies them to `bricks_modules/` directory
3. Updates references to point to `./bricks_modules/`
4. Includes everything in the published package

Your module becomes self-contained and portable.

### Disable module resolution

If you **don't** want to include external modules:

```bash
bricks blueprint publish --resolve-modules=false
```

Bluebricks warns you about external references but won't include them.

## Terraform version

**Default version:** 1.5.7

Specify a different version in `bricks.json`:

```json
{
  "native": {
    "type": "terraform",
    "path": ".",
    "version": "1.6.5"
  }
}
```

For the full version limits table and examples, see [version pinning](https://bluebricks.co/docs/core-concepts/packages/artifacts-overview/terraform-open-tofu/..#version-pinning).

## State management

Bluebricks automatically manages state using its built-in HTTP backend. Do not include `backend.tf` or backend configuration blocks in your Terraform code.

For details on managed state, locking, and encryption, see [Terraform/OpenTofu](https://bluebricks.co/docs/core-concepts/packages/artifacts-overview/terraform-open-tofu/..#managed-state-details).

To work locally with remote state for debugging or development, see [Develop Terraform Locally](https://bluebricks.co/docs/help/guides/develop-terraform-locally).

### Publishing with existing state

If you're migrating existing Terraform infrastructure, include your state file:

```bash
bricks blueprint publish --state
```

Requirements:

* Place `terraform.tfstate` in your Terraform directory
* Bluebricks packages it with your module
* State is stored securely in Bluebricks

## Variables and outputs mapping

Variables and outputs are auto-discovered during publish. Bluebricks parses your `variables.tf` and `outputs.tf`, then converts them to `props` and `outs` in `bricks.json`. See [Terraform/OpenTofu inputs and outputs](https://bluebricks.co/docs/core-concepts/packages/artifacts-overview/terraform-open-tofu/..#inputs) for the full mapping details and examples.

## Examples

<details>

<summary>Publishing a VPC module</summary>

```
vpc_module/
├── main.tf
├── variables.tf
├── outputs.tf
└── versions.tf
```

```bash
cd vpc_module
bricks blueprint prepare --source . --iac-type terraform
bricks blueprint publish
```

</details>

<details>

<summary>Publishing with local modules</summary>

```
my-infrastructure/
├── main.tf              # References ../common/networking
├── variables.tf
└── outputs.tf

../common/networking/
├── vpc.tf
├── subnets.tf
└── outputs.tf
```

```bash
cd my-infrastructure
bricks blueprint prepare --source . --iac-type terraform
bricks blueprint publish
```

Bluebricks automatically detects `../common/networking`, copies it to `bricks_modules/common/networking/`, updates your references, and packages everything together. Your published module is now self-contained.

</details>

<details>

<summary>Migrating existing infrastructure</summary>

```bash
cd production-vpc
terraform show  # Verify state exists

# Publish with state
bricks blueprint prepare --source . --iac-type terraform
bricks blueprint publish --state
```

Bluebricks stores your state securely, enables locking to prevent conflicts, and provides a full audit trail.

</details>

## Common options

<details>

<summary>Prepare options</summary>

```bash
bricks blueprint prepare \
  --source ./terraform \
  --iac-type terraform \
  --output ./my-package \
  --package-name my-vpc
```

* `--source`: Path to Terraform directory
* `--iac-type`: Must be `terraform`
* `--output`: Where to create package (default: current directory)
* `--package-name`: Custom package name (default: directory name)
* `--refactor`: Create `bricks.json` without moving files

</details>

<details>

<summary>Publish options</summary>

```bash
bricks blueprint publish \
  --src ./my-package \
  --resolve-modules=true \
  --state
```

* `--src`: Package directory (default: current directory)
* `--resolve-modules`: Include external modules (default: `true`)
* `--state`: Include terraform.tfstate file

</details>

## Generated package structure

<details>

<summary>After prepare</summary>

```
my-package/
├── bricks.json          # Package metadata
└── src/
    └── terraform/       # Your .tf files
        ├── main.tf
        ├── variables.tf
        ├── outputs.tf
        └── versions.tf
```

</details>

<details>

<summary>After publish with --resolve-modules</summary>

```
my-package/
├── bricks.json
└── src/
    └── terraform/
        ├── main.tf
        ├── variables.tf
        ├── outputs.tf
        ├── versions.tf
        └── bricks_modules/     # External modules copied here
            └── common/
                └── networking/
                    ├── vpc.tf
                    └── outputs.tf
```

</details>

## Best practices

* Test locally before publishing
* Use `--resolve-modules` for portability
* Include state with `--state` when migrating existing infrastructure
* Version your packages with semantic versioning

## See also

* [Develop Terraform Locally](https://bluebricks.co/docs/help/guides/develop-terraform-locally): download state config for local debugging
* [Terraform/OpenTofu](https://bluebricks.co/docs/core-concepts/packages/artifacts-overview/terraform-open-tofu): artifact reference and features overview
* [Creating Blueprints](https://bluebricks.co/docs/core-concepts/packages/blueprints-overview/creating-blueprints): compose artifacts into blueprints
* [Packages](https://bluebricks.co/docs/core-concepts/packages): artifact types and packaging concepts
