---
description: |
  Install external Packer plugins that extend Packer functionality.
page_title: Install Plugins
---

# Installing Plugins

Packer plugins are separate, standalone applications that perform tasks during each build.

This page explains how to install external plugins. Refer to [Integrations](/packer/integrations) for a list of available plugins and their documentation.

Depending on the template type you're using (HCL2 or legacy JSON), the methods for installing plugins may differ.

If you're using HCL2, `packer init` is recommended as you can install all your requirements with one
command, and those requirements are explicitly documented in the template.

`packer plugins install` is also used to automate the installation from a source, and will need to
be repeated for as many plugins as you need.
We recommend this for JSON as the template cannot contain the information about the required plugins.

While `packer plugins install` is able to install plugins remotely, you can use
the `--path` flag to install locally-sourced plugin binaries.
This is typically useful in two general cases:

1. You are in an environment with restricted access to a plugin's source.
1. You are trying to install a development version of a plugin for testing.

Refer to the [Installation Guides](#installation-guides) section of this page for information about
each method, including usage examples.

The remainder of this document documents how Packer interacts with plugins.
We encourage you to read this to get familiar with this process, as it will help you troubleshoot
builds if you encounter problems with plugins.

## Source Addresses

A plugin's source address is conceptually where a plugin binary can be downloaded from.
Packer also uses this source as a global unique identifier.
This source translates directly to the file hierarchy in which the plugin binaries will be
installed.

Source addresses are a URL, without a scheme (e.g. `"https://"`), query (e.g. `?arg=val`), or
fragment (e.g. `#anchor`).

Example: `github.com/hashicorp/happycloud`

#### Github sources

Github sources all follow this convention: `<hostname>/<namespace>/<type>`.

- **Hostname:** The hostname of the location/service that distributes the plugin.

- **Namespace:** An organizational namespace within the specified host.
  This often is the organization that maintains the plugin.

- **Type:** A short name for the platform or system the plugin manages. The
  type is usually the plugin's preferred local name.

For example, the fictional `happycloud` plugin could belong to the
`hashicorp` namespace on `github.com`, so its `source` could be
`github.com/hashicorp/happycloud`,

-> Note: the actual _repository_ that happycloud comes from must always have
the name format `github.com/hashicorp/packer-plugin-happycloud`, but the
source voluntarily omits the redundant `packer-plugin-` prefix for brevity.

The source address with all the components given explicitly is called the
plugin's _fully-qualified address_. You will see fully-qualified addresses in
various outputs, like error messages.

### Source and local hierarchy

As mentioned above, each source URL will directly impact how Packer will install
a plugin to the local plugin directory.
Each component of the path described will become a subdirectory, and finally,
plugin binaries are installed at the end of that hierarchy.
Multiple versions can be installed along one another.

In order for the binaries installed in this directory to be discovered and used
by Packer, they must follow this set of rules:

1. The name of the binary must be in the `packer-plugin-<name>_<version>_x<api_version>_<os>_<arch>(.exe)?` format
1. The binary must be accompanied by a SHA256SUM file, which must contain the SHA256 hash of the binary
1. The `describe` command of the binary must return informations that match the plugin's name, namely:

    a. The plugin version must match the name

    b. The API version must match the name's

1. The version must be canonical: e.g. 1.0.1 (valid) vs. 01.000.01 (invalid)
1. The version must be valid semver (e.g. 1.0.0)
1. Pre-releases are accepted, but must be `-dev` only.
1. Metadata shall not be in the name of the plugin binary, only metadata-free versions will be considered valid for discovery purposes.

## Plugin Discovery Workflow

At initialization, Packer attempts to discover the plugins installed locally. The
logic follows what's described in Configuring Packer's
[plugin directory](/packer/docs/configure#packer-s-plugin-directory)
section.

While Packer is not verbose during this step, you can peek into what it is discovering
with `PACKER_LOG=1` enabled, where you can find log lines similar to the following:

```shell
[TRACE] discovering plugins in [...]
[INFO] Discovered potential plugin: [...]
```

Once this discovery step has finished, each discovered plugin will be ready to use
by Packer, on the highest available version.

Example:

```shell
<packer_plugin_dir>
└── github.com
    └── hashicorp
        └── happycloud
            ├── packer-plugin-happycloud_v1.1.8_x5.0_linux_amd64
            ├── packer-plugin-happycloud_v1.1.8_x5.0_linux_amd64_SHA256SUM
            ├── packer-plugin-happycloud_v1.2.8_x5.0_linux_amd64
            └── packer-plugin-happycloud_v1.2.8_x5.0_linux_amd64_SHA256SUM
```

In this example, the `happycloud` plugin will be the one and used to serve
happycloud-related components, in version 1.2.8.

### HCL2 and `required_plugins`

The aforementioned logic is all that can apply to legacy JSON templates.
HCL2 however introduces the concept of `required_plugins` blocks.
These blocks allow you to declare what plugins your template needs in order
to be able to build an artifact, along with version constraints.

Example:

```hcl2
packer{
  required_plugins {
    happycloud = {
      source  = "github.com/hashicorp/happycloud"
      version = "= 1.1.8"
    }
  }
}
```

With this constraint specified, Packer will not only be able to remotely install
the plugin you need with `packer init` (provided it is hosted on a remote that the command
supports), but also restrict which versions can be used for building the template.

Using the aforementioned plugin hierarchy, a constraint like the one above will
take precedence over the usual discovery process, this time yielding version 1.1.8
of the happycloud plugin for serving its components.

## Installation Guides

### Packer init

-> Using `packer init` requires using HCL2 templates. If you are using JSON and
   want to start using HCL2 templates in order to leverage this feature, please
   refer to our [JSON to HCL](/packer/docs/templates/json_to_hcl) guide.

In order to use `packer init` for managing installation of your plugins, there are
two steps required.

First, add a [`required_plugins`](/packer/docs/templates/hcl_templates/blocks/packer#specifying-plugin-requirements)
block to your [packer block](/packer/docs/templates/hcl_templates/blocks/packer).

Each block will tell Packer what version(s) of a particular plugin can be installed.
Make sure to set a valid
[version constraint string](/packer/docs/templates/hcl_templates/blocks/packer#version-constraints).

Here is an example `required_plugins` block:

```hcl
packer {
  required_plugins {
    myawesomecloud = {
      version = ">= 2.7.0"
      source = "github.com/hashicorp/myawesomecloud"
    }
    happycloud = {
      version = ">= 1.1.3"
      source = "github.com/hashicorp/happycloud"
    }
  }
}
```

Once your template contains those `required_plugins`, run
[`packer init`](/packer/docs/commands/init) to install all missing plugin
binaries.
Given the above example, Packer will try to look for a GitHub
repository owned by user or organization `hashicorp` named
`packer-plugin-myawesomecloud` and `packer-plugin-happycloud`.

-> Note: `packer init` tries to install plugins matching the version constraints required by the template.
   Running `packer init` multiple times on the same template will result in no changes if all matching plugins
   have already been installed.  If you want to update a plugin or force re-installation, you may use the
   `--update` or `--force` arguments.

### Packer plugins install

Plugin installation via `packer plugins install` works similar to that of the `packer init` command, but
no `required_plugins` block are required.

```shell
packer plugins install github.com/hashicorp/vagrant
```

-> You can only install one plugin per invocation of the command. If you need to install
   a specific version of a plugin, you can specify a version to install as an optional
   argument to the command line.
   e.g.: `packer plugins install "github.com/hashicorp/vagrant" "v1.0.1"`

The command will install the plugin in the `PACKER_CONFIG_DIR` set, or its
default location, which depends on the OS/environment, as documented in
[Configuring Packer](/packer/docs/configure#packer-s-plugin-directory).

#### Using packer plugins install to install a local copy of a binary

If the plugin you want to install cannot be installed remotely, you can use the
`--path` argument for `packer plugins install` in order to use the provided
plugin binary as source.

Example:

```shell
$ ls -l packer-plugin-happycloud
-rwxrwxr-x  1 root root 44745210 Jan 01 1979 packer-plugin-happycloud
$ PACKER_PLUGIN_PATH=/root/plugins packer plugins install --path ./packer-plugin-happycloud "github.com/hashicorp/happycloud"
Successfully installed plugin github.com/hashicorp/happycloud from /root/packer-plugin-happycloud to /root/plugins/github.com/hashicorp/happycloud/packer-plugin-happycloud_v1.2.8-dev_x5.0_linux_amd64
```

-> Note: the version does not need to be specified, Packer will automatically
   determine which version to install based on the plugin's `describe` output.
