---
title: "Artifactory"
weight: 200
---

Publish your artifacts to an Artifactory instance.

## How it works

You can declare multiple Artifactory instances.
All binaries generated by your `builds` section will be pushed to
each configured Artifactory.

If you have only one Artifactory instance,
the configuration is as easy as adding the
upload target, and a username to your `.goreleaser.yaml` file:

```yaml
artifactories:
  - name: production
    target: http://<Your-Instance>:8081/artifactory/example-repo-local/{{ .ProjectName }}/{{ .Version }}/
    username: goreleaser
```

Prerequisites:

- A running Artifactory instances
- A user + password / client x509 certificate / API key with grants to upload
  an artifact

### Target

The `target` is the URL to upload the artifacts to (_without_ the name of the
artifact).

An example configuration for `goreleaser` in upload mode `binary` with the
target can look like

```yaml
- mode: binary
  target: "http://artifacts.company.com:8081/artifactory/example-repo-local/{{ .ProjectName }}/{{ .Version }}/{{ .Os }}/{{ .Arch }}{{ if .Arm }}{{ .Arm }}{{ end }}"
```

And will result in a final deployment like
`http://artifacts.company.com:8081/artifactory/example-repo-local/goreleaser/1.0.0/Darwin/x86_64/goreleaser`.

Supported variables:

- `Version`
- `Tag`
- `ProjectName`
- `Os`
- `Arch`
- `Arm`

> [!NOTE]
> Variables _Os_, _Arch_ and _Arm_ are only supported in upload mode `binary`.

### Username

Your configured username needs to be authenticated against your Artifactory.

You can have the username set in the configuration file as shown above, or you
can have it read from an environment variable. The configured name of your
Artifactory instance will be used to build the environment variable name. This
way we support authentication for multiple instances. This also means that the
`name` per configured instance needs to be unique per GoReleaser configuration.

The name of the environment variable will be `ARTIFACTORY_NAME_USERNAME`.
If your instance is named `production`, you can store the username in the
environment variable `ARTIFACTORY_PRODUCTION_USERNAME`.
The name will be transformed to uppercase.

If a configured username is found in the configuration file, then the
environment variable is not used at all.

### Password / API Key

The password or API key will be stored in an environment variable.
The configured name of your Artifactory instance will be used.
With this way we support auth for multiple instances.
This also means that the `name` per configured instance needs to be unique
per goreleaser configuration.

The name of the environment variable will be `ARTIFACTORY_NAME_SECRET`.
If your instance is named `production`, you need to store the secret in the
environment variable `ARTIFACTORY_PRODUCTION_SECRET`.
The name will be transformed to uppercase.

### Client authorization with x509 certificate (mTLS / mutual TLS)

If your artifactory server supports authorization with mTLS (client
certificates), you can provide them by specifying the location of an x509
certificate/key pair of pem-encode files.

```yaml
artifactories:
  - name: production
    target: http://<Your-Instance>:8081/artifactory/example-repo-local/{{ .ProjectName }}/{{ .Version }}/
    client_x509_cert: path/to/client.cert.pem
    client_x509_key: path/to/client.key.pem
```

This will offer the client certificate during the TLS handshake, which your
artifactory server may use to authenticate and authorize you to upload.

### Server authentication

You can authenticate your Artifactory TLS server adding a trusted X.509
certificate chain in your configuration.

The trusted certificate chain will be used to validate the server certificates.

You can set the trusted certificate chain using the `trusted_certificates`
setting the artifactory section with PEM encoded certificates on a YAML literal
block like this:

```yaml
puts:
  - name: "some artifactory server with a private TLS certificate"
    #...(other settings)...
    trusted_certificates: |
      -----BEGIN CERTIFICATE-----
      MIIDrjCCApagAwIBAgIIShr2zchZo+8wDQYJKoZIhvcNAQENBQAwNTEXMBUGA1UE
      ...(edited content)...
      TyzMJasj5BPZrmKjJb6O/tOtEIJ66xPSBTxPShkEYHnB7A==
      -----END CERTIFICATE-----
      -----BEGIN CERTIFICATE-----
      MIIDrjCCApagAwIBAgIIShr2zchZo+8wDQYJKoZIhvcNAQENBQAwNTEXMBUGA1UE
      ...(edited content)...
      TyzMJasj5BPZrmKjJb6O/tOtEIJ66xPSBTxPShkEYHnB7A==
      -----END CERTIFICATE-----
```

### Client checksum headers

With its default checksum policy, Artifactory requires [checksum headers](https://jfrog.com/help/r/what-are-client-checksum-server-checksum-and-checksum-policy-in-local-repositories) from the client for all uploaded artifacts.
When the client deploys a checksum header with a file, Artifactory calculates the file's checksum and compares it to the client-provided value.

You can add the checksum headers to your upload configuration using the `custom_headers` field:

```yaml
artifactories:
  - name: production
    target: http://<Your-Instance>:8081/artifactory/example-repo-local/{{ .ProjectName }}/{{ .Version }}/
    custom_headers:
      X-Checksum-MD5: "{{ md5 .ArtifactPath }}"
      X-Checksum-SHA1: "{{ sha1 .ArtifactPath }}"
      X-Checksum-SHA256: "{{ sha256 .ArtifactPath }}"
```

## Customization

Of course, you can customize a lot of things:

```yaml {filename=".goreleaser.yaml"}
artifactories:
  # You can have multiple Artifactory instances.
  - # Unique name of your artifactory instance. Used to identify the instance
    name: production

    # IDs of the artifacts you want to upload.
    ids:
      - foo
      - bar

    # File extensions to filter for.
    # This might be useful if you have multiple packages with different
    # extensions with the same ID, and need to upload each extension to
    # a different place (e.g. nFPM packages).
    exts:
      - deb
      - rpm

    # Matrix will run the upload for each possible combination of the given
    # values.
    # The keys will be available as template variables in the `target` and
    # `custom_headers` fields.
    #
    # This feature is only available in GoReleaser Pro.
    matrix:
      foo: [bar zaz]
      something: [foobar somethingelse anotherthing]

    # Upload mode. Valid options are `binary` and `archive`.
    #
    # If mode is `archive`, variables _Os_, _Arch_ and _Arm_ for target name
    #   are not supported. In that case these variables are empty.
    #
    # If mode is `binary`, you'll need to have the archives section setup with
    #   format "binary" as well.
    #
    # Default: 'archive'.
    mode: archive

    # URL of your Artifactory instance + path to deploy to
    target: http://artifacts.company.com:8081/artifactory/example-repo-local/{{ .ProjectName }}/{{ .Version }}/

    # Tells goreleaser not to append the artifact name to the target URL. You must do this manually
    custom_artifact_name: true

    # An optional username that will be used for the deployment for basic auth.
    #
    # Templates: allowed. {{< g_inline_version "v2.12" >}}
    username: deployuser

    # An optional password that will be used for the deployment for basic auth.
    #
    # Templates: allowed.
    # {{< g_inline_version "v2.12" >}}
    password: '{{ readFile "~/.config/foo" }}'

    # Client certificate and key (when provided, added as client cert to TLS connections)
    client_x509_cert: /path/to/client.cert.pem
    client_x509_key: /path/to/client.key.pem

    # A map of custom headers e.g. to support client checksums.
    custom_headers:
      X-Checksum-MD5: "{{ md5 .ArtifactPath }}"
      X-Checksum-SHA1: "{{ sha1 .ArtifactPath }}"
      X-Checksum-SHA256: "{{ sha256 .ArtifactPath }}"

    # Upload checksums.
    checksum: true

    # Upload metadata.json and artifacts.json.
    meta: true

    # Upload signatures.
    signature: true

    # Skip this upload configuration.
    #
    # Templates: allowed.
    # {{< g_inline_version "v2.7" >}}
    skip: "{{gt .Patch 0}}"

    # Certificate chain used to validate server certificates
    trusted_certificates: |
      -----BEGIN CERTIFICATE-----
      MIIDrjCCApagAwIBAgIIShr2zchZo+8wDQYJKoZIhvcNAQENBQAwNTEXMBUGA1UE
      ...(edited content)...
      TyzMJasj5BPZrmKjJb6O/tOtEIJ66xPSBTxPShkEYHnB7A==
      -----END CERTIFICATE-----

    # You can add extra pre-existing files to the upload.
    #
    # The filename on the release will be the last part of the path (base).
    # If another file with the same name exists, the last one found will be used.
    # These globs can also include templates.
    #
    # {{< g_inline_version "v2.1" >}}
    extra_files:
      - glob: ./path/to/file.txt
      - glob: ./glob/**/to/**/file/**/*
      - glob: ./glob/foo/to/bar/file/foobar/override_from_previous
      - glob: ./single_file.txt
        # Templates: allowed.
        name_template: file.txt # note that this only works if glob matches 1 file only

    # Additional templated extra files to uploaded.
    # Those files will have their contents pass through the template engine,
    # and its results will be uploaded.
    #
    # {{< g_inline_pro >}}
    # {{< g_inline_version "v2.1" >}}
    # Templates: allowed.
    templated_extra_files:
      - src: LICENSE.tpl
        dst: LICENSE.txt

    # Upload only the files defined in extra_files.
    #
    # {{< g_inline_version "v2.1" >}}
    extra_files_only: true
```

{{< g_featpro >}}

These settings should allow you to push your artifacts into multiple
**Artifactory** instances.

{{< g_templates >}}
