# Managing tag-based Custom Assembly with Terraform

URL: https://chainguard-docs-preview-git-tpguardener-image-suggestions-docs.chainguard.app/chainguard/containers/custom-assembly/tag-based-custom-assembly/terraform.md
Last Modified: September 29, 2026
Tags: Chainguard Containers, Procedural, Custom Assembly, Automation

How to use the Chainguard Terraform provider to create overlays and bind them to specific tags of a Custom Assembly repository.

 Note: Tag-based Custom Assembly is in beta. Contact your Chainguard account team to enable it for your organization.
This guide shows how to manage tag-based Custom Assembly with the Chainguard Terraform provider. You define overlays with the chainguard_image_overlay resource and bind them to repositories with the chainguard_image_overlay_binding resource.
For an explanation of overlays, bindings, and tag selectors, see Overview of tag-based Custom Assembly.
Prerequisites Before you start, you need the following:
Tag-based Custom Assembly enabled for your organization. Contact your Chainguard account team to enable it. Terraform and the Chainguard Terraform provider, version 0.5.0 or later. To configure the provider, see Introduction to the Chainguard Terraform provider. An identity with the registry.overlays.edit capability, such as one bound to the built-in editor or owner role. A repository in your organization with no standard Custom Assembly customization. A repository can&rsquo;t use both. Look up your organization and repository Overlays belong to your organization, and bindings belong to a repository, so you need the IDs of both. The following configuration requires the Chainguard provider and uses data sources to look up the example.com organization and its python repository:
terraform { required_providers { chainguard = { source = &#34;chainguard-dev/chainguard&#34; version = &#34;&gt;= 0.5.0&#34; } } } data &#34;chainguard_group&#34; &#34;org&#34; { name = &#34;example.com&#34; } data &#34;chainguard_image_repo&#34; &#34;python&#34; { parent_id = data.chainguard_group.org.id name = &#34;python&#34; } locals { python_repo_id = data.chainguard_image_repo.python.items[0].id }The chainguard_image_repo data source returns a list of matching repositories. The python_repo_id local value holds the ID of the first match, which the binding examples later in this guide use.
Create overlays Each chainguard_image_overlay resource defines a named set of customizations. For an overlay that only adds packages, set the packages attribute. The following example defines two overlays that add packages:
resource &#34;chainguard_image_overlay&#34; &#34;typer&#34; { parent_id = data.chainguard_group.org.id name = &#34;typer&#34; packages = [&#34;py3.13-typer&#34;] } resource &#34;chainguard_image_overlay&#34; &#34;debug_tools&#34; { parent_id = data.chainguard_group.org.id name = &#34;debug-tools&#34; packages = [&#34;strace&#34;, &#34;gdb&#34;] }Package names can use the {{major}} and {{minor}} placeholders, as in py{{major}}.{{minor}}-cryptography. For details, see Version templates in package names.
To add other customizations, such as certificates, environment variables, or annotations, set the config attribute instead of packages. An overlay can set one of the two, but not both. The config attribute takes a JSON-encoded configuration. Its field names follow the Chainguard API, not the YAML file that chainctl accepts, and some names differ. For example, the user an image runs as is accounts.run_as in config but accounts.run-as in a chainctl file. For the field names, see the chainguard_image_overlay schema.
The following example uses jsonencode to build an overlay that adds an internal certificate authority, an environment variable, and a package:
resource &#34;chainguard_image_overlay&#34; &#34;internal_ca&#34; { parent_id = data.chainguard_group.org.id name = &#34;internal-ca&#34; config = jsonencode({ contents = { packages = [&#34;curl&#34;] } environment = { REQUESTS_CA_BUNDLE = &#34;/etc/ssl/certs/ca-certificates.crt&#34; } certificates = { additional = [{ name = &#34;internal-ca&#34; content = file(&#34;${path.module}/internal-ca.pem&#34;) }] } }) }The file function reads the certificate from internal-ca.pem in the same directory as your configuration, so the certificate text doesn&rsquo;t need to appear in the configuration itself. For the full list of supported fields, see Supported customizations.
Bind overlays to tags Each chainguard_image_overlay_binding resource attaches one overlay to one repository. The tag_selector block chooses which tags the overlay applies to.
To apply an overlay to specific tags, set kind to EXACT and list the tags:
resource &#34;chainguard_image_overlay_binding&#34; &#34;typer&#34; { repo_id = local.python_repo_id overlay_id = chainguard_image_overlay.typer.id tag_selector { kind = &#34;EXACT&#34; tags = [&#34;3.13&#34;, &#34;3.13-dev&#34;] } }To apply an overlay to every -dev tag, set kind to VARIANT and variant_type to DEV:
resource &#34;chainguard_image_overlay_binding&#34; &#34;debug_tools&#34; { repo_id = local.python_repo_id overlay_id = chainguard_image_overlay.debug_tools.id tag_selector { kind = &#34;VARIANT&#34; variant_type = &#34;DEV&#34; } }To apply an overlay to every tag, set kind to ALL:
tag_selector { kind = &#34;ALL&#34; }You can bind a given overlay to a repository only once. To apply an overlay to more tags, change its binding&rsquo;s selector instead of adding a second binding.
To create the overlays and bindings, apply the configuration:
terraform applyAfter Terraform creates the bindings, Chainguard rebuilds the matching tags. To check on the builds, run chainctl images repos build list --repo python --parent example.com.
Change or remove customizations The overlay and binding resources don&rsquo;t support in-place updates. When you change an overlay&rsquo;s name, packages, or configuration, or a binding&rsquo;s selector, Terraform deletes the resource and creates a new one. Replacing an overlay gives it a new ID, so Terraform also replaces the bindings that refer to it.
Each replacement removes the customization before adding it back, so Chainguard might rebuild the affected tags twice: once without the customization and once with it. Review the plan before you apply changes to repositories that serve production traffic.
To remove a customization, delete the binding resource from your configuration and apply. Chainguard rebuilds the tags that the binding matched without the removed overlay. Any other matching overlays still apply. You can&rsquo;t delete an overlay while a binding still refers to it. Terraform removes the binding first when you delete both in one change.
Learn more Overview of tag-based Custom Assembly Managing tag-based Custom Assembly with chainctl chainguard_image_overlay in the Terraform Registry chainguard_image_overlay_binding in the Terraform Registry 
