Publish Terraform Modules with JFrog CLI

Run Terraform commands with Artifactory provider integration and optional build-info collection.

This topic covers the following tasks:

When to Use

Use jf terraform to publish Terraform providers and modules to Artifactory. This command packages and deploys Terraform artifacts — it does not wrap terraform init or terraform plan.

📘

Package Alias (Ghost Frog)

Package Alias does not intercept terraform commands. Supported tools are mvn, gradle, npm, yarn, pnpm, go, pip, pipenv, poetry, dotnet, nuget, docker, gem, and bundle. See Use JFrog CLI Package Alias for setup and the full tool list.

Prerequisites

  • Configure a server with jf config add or jf c add.
  • Authentication to Artifactory is required.
  • A local Terraform repository must exist in Artifactory. Create one via Administration → Repositories → Add Repositories → Local, selecting Terraform as the package type.
  • Run jf terraform-config in the project directory before the first operation.
📘

Note

: The terraform CLI binary is not required. jf terraform packages and publishes modules directly — it never invokes the terraform binary.


Configuration: jf terraform-config

Generate Terraform configuration for deployment to Artifactory. Run this once per project before your first Terraform operation.

To configure Terraform for Artifactory:

  1. From your project directory, run jf terraform-config with --server-id-deploy and --repo-deploy (see Non-Interactive Configuration with Flags).
  2. Confirm .jfrog/projects/terraform.yaml exists (see How to Verify).

Synopsis

jf terraform-config [options]

Aliases: tfc

Configuration Options

FlagDefaultDescription
--globalfalseSet to true for global configuration (all projects). Specific projects can override.
--repo-deployRepository for artifacts deployment
--server-id-deployArtifactory server ID for deployment. Configure with jf config add.

Configuration Examples

View Help

jf terraform-config --help

Non-Interactive Configuration with Flags

jf terraform-config --server-id-deploy=<server-id> --repo-deploy=<repo-name>

Where:

  • <server-id>: The server ID configured using jf config add
  • <repo-name>: The name of the Terraform repository in Artifactory

For example:

jf terraform-config --server-id-deploy=my-server --repo-deploy=terraform-local

Why Run Config First?

You must run jf terraform-config before using jf terraform for deployment. The config creates .jfrog/projects/terraform.yaml specifying the Artifactory repository for Terraform provider/module uploads. Without it, jf terraform does not know where to deploy artifacts.

👍

Shortcut

: In CI/CD, pass all flags non-interactively so the config step is fully automated and reproducible. Ensure the .jfrog/projects/terraform.yaml file does not already exist before running, or delete it first — if the file exists, the CLI prompts interactively: Configuration file already exists. Override it? (y/n), which blocks non-TTY environments.

Configuration Notes

  • Deployment only: Terraform config supports artifact deployment but not resolution. Terraform providers are resolved via Terraform's own registry mechanism.
  • Run once per project: Re-run when changing the deployment repository. If the config file already exists, the CLI will prompt for confirmation before overwriting.

Expected Output

$ jf terraform-config --server-id-deploy=my-server --repo-deploy=terraform-local
terraform build config successfully created.

How to Verify

After running, confirm the configuration exists:

cat .jfrog/projects/terraform.yaml

Expected file contents:

version: 1
type: terraform
deployer:
    repo: terraform-local
    serverId: my-server
📘

Note

: Unlike other build tools, there is no resolver section — Terraform config supports deployment only.


Build: jf terraform

Run Terraform commands with Artifactory provider integration and optional build-info collection.

To publish Terraform modules to Artifactory:

  1. Run jf terraform-config in the project directory if you have not already (see Configuration).
  2. From the module directory, run jf terraform (or jf tf) with the publish subcommand and required --namespace, --provider, and --tag flags (see Build Examples).

Synopsis

jf terraform <terraform-arguments> [options]

Aliases: tf

Arguments

ArgumentRequiredDescription
<terraform-arguments>YesTerraform subcommand and options. Only publish (alias p) is supported.

Build Options

FlagDefaultDescription
--build-nameBuild name for build-info. Requires --build-number.
--build-numberBuild number for build-info. Requires --build-name.
--exclusionsSemicolon-separated exclusions. Wildcards * and ? are supported.
--moduleOptional module name for build-info. Requires --build-name and --build-number.
--namespaceTerraform namespace. Required for all publish operations.
--projectJFrog Artifactory project key
--providerTerraform provider. Required for all publish operations.
--tagTerraform package tag. Required for all publish operations.

Build Examples

Publish a Terraform Module

The command creates a package for the Terraform module in the current directory and publishes it to the configured Terraform repository:

jf tf p --namespace=<namespace> --provider=<provider> --tag=<tag>

Where:

  • <namespace> is the Terraform namespace (for example, example, myorg)
  • <provider> is the Terraform provider name (for example, aws, azure, gcp)
  • <tag> is the version tag (for example, v0.0.1)

For example:

jf tf p --namespace=example --provider=aws --tag=v0.0.1

Publish with Exclusions

The published package will not include module paths matching test or ignore:

jf tf p --namespace=example --provider=aws --tag=v0.0.1 --exclusions="*test*;*ignore*"

Publish with Build-Info

The published module will be recorded as an artifact of build my-build with build number 1:

jf tf p --namespace=example --provider=aws --tag=v0.0.1 --build-name=my-build --build-number=1
jf rt build-publish my-build 1

Important Notes

  • Mandatory flags: --namespace, --provider, and --tag are required for all publish operations — both module and provider publishing.
  • Terraform providers: This command is used to publish and manage Terraform providers and modules in Artifactory, not for general Terraform workflows.
  • Build-info: Use --build-name and --build-number to track provider/module deployments.

CI/CD Example (GitHub Actions)

# .github/workflows/build.yml
steps:
  - uses: actions/checkout@v4
  - name: Setup JFrog CLI
    uses: jfrog/setup-jfrog-cli@v4
    env:
      JF_URL: ${{ vars.JF_URL }}
      JF_ACCESS_TOKEN: ${{ secrets.JF_ACCESS_TOKEN }}
  - name: Configure Terraform
    run: jf terraform-config --server-id-deploy=setup-jfrog-cli-server --repo-deploy=terraform-local
  - name: Publish Terraform module
    run: jf tf p --namespace=example --provider=aws --tag=v0.0.1 --build-name=my-terraform --build-number=${{ github.run_number }}
  - name: Publish build info
    run: jf rt build-publish my-terraform ${{ github.run_number }}

Troubleshooting

SymptomCauseFix
The repository '<name>' does not existTerraform repository not yet created in ArtifactoryCreate a local Terraform repository in Artifactory, then re-run jf terraform-config with the correct name
no config file was foundjf terraform-config was not runRun jf terraform-config in the project directory
401 / 403 on publishInvalid credentials or insufficient permissionsRe-run jf config add with a valid access token
the --namespace, --provider and --tag options are mandatoryRequired flags not providedPass --namespace, --provider, and --tag on every publish
No .tf files foundCommand run in wrong directoryEnsure you are in a directory containing Terraform module files
Unwanted files included in packageTest or doc files not excludedUse --exclusions="*test*;*.md" to filter them out
Config step hangs in CI/CDExisting config file triggers interactive promptDelete .jfrog/projects/terraform.yaml before re-running jf terraform-config in non-TTY environments

Enable debug logging: export JFROG_CLI_LOG_LEVEL=DEBUG


Related Topics