# S3 Backend

You may install tools directly from Amazon S3 or S3-compatible storage (like MinIO) using the `s3` backend. This backend is ideal for enterprise teams hosting proprietary tools in private S3 buckets.

The code for this is inside of the mise repository at [`./src/backend/s3.rs`](https://github.com/jdx/mise/blob/main/src/backend/s3.rs).

## Usage

The following installs a tool from an S3 bucket:

```sh
mise use -g "s3:my-tool[url=s3://my-bucket/tools/my-tool-v1.0.0.tar.gz]@1.0.0"
```

The version will be set in `~/.config/mise/config.toml` with the following format:

```toml
[tools]
"s3:my-tool" = { version = "1.0.0", url = "s3://my-bucket/tools/my-tool-v1.0.0.tar.gz" }
```

## Authentication

The S3 backend uses the AWS SDK default credential chain. Credentials are loaded from (in order):

1. Environment variables: `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY`
2. AWS credentials file: `~/.aws/credentials`
3. IAM roles (when running on AWS infrastructure)

```sh
# Set credentials via environment variables
export AWS_ACCESS_KEY_ID="your-access-key"
export AWS_SECRET_ACCESS_KEY="your-secret-key"
export AWS_DEFAULT_REGION="us-east-1"

mise install
```

## Tool Options

The following [tool-options](/dev-tools/#tool-options) are available for the `s3` backend—these
go in `[tools]` in `mise.toml`.

### `url` (Required)

Specifies the S3 URL to download the tool from. The URL supports templating with <code v-pre>{{ version }}</code>:

```toml
[tools]
"s3:my-tool" = { version = "1.0.0", url = "s3://my-bucket/tools/my-tool-v{{ version }}.tar.gz" }
```

### `endpoint`

Specify a custom S3-compatible endpoint for services like MinIO, DigitalOcean Spaces, or self-hosted S3:

```toml
[tools."s3:my-tool"]
version = "1.0.0"
url = "s3://my-bucket/tools/my-tool-v{{ version }}.tar.gz"
endpoint = "http://minio.internal:9000"
```

### `region`

Specify the AWS region for the S3 bucket:

```toml
[tools."s3:my-tool"]
version = "1.0.0"
url = "s3://my-bucket/tools/my-tool-v{{ version }}.tar.gz"
region = "us-west-2"
```

### Platform-specific URLs

For tools that need different downloads per platform, use the table format:

```toml
[tools."s3:my-tool"]
version = "1.0.0"

[tools."s3:my-tool".platforms]
macos-x64 = { url = "s3://my-bucket/tools/my-tool-v1.0.0-macos-x64.tar.gz" }
macos-arm64 = { url = "s3://my-bucket/tools/my-tool-v1.0.0-macos-arm64.tar.gz" }
linux-x64 = { url = "s3://my-bucket/tools/my-tool-v1.0.0-linux-x64.tar.gz" }
```

### `checksum`

Verify the downloaded file with a checksum:

```toml
[tools."s3:my-tool"]
version = "1.0.0"
url = "s3://my-bucket/tools/my-tool-v1.0.0.tar.gz"
checksum = "sha256:a1b2c3d4e5f6789..."
```

_Instead of specifying the checksum here, you can use [mise.lock](/dev-tools/mise-lock) to manage checksums._

### `size`

Verify the downloaded object size:

```toml
[tools."s3:my-tool"]
version = "1.0.0"
url = "s3://my-bucket/tools/my-tool-v1.0.0.tar.gz"
size = "12345678"
```

You can specify different sizes for different platforms:

```toml
[tools."s3:my-tool"]
version = "1.0.0"

[tools."s3:my-tool".platforms]
macos-arm64 = { url = "s3://my-bucket/tools/my-tool-v1.0.0-macos-arm64.tar.gz", size = "9876543" }
linux-x64 = { url = "s3://my-bucket/tools/my-tool-v1.0.0-linux-x64.tar.gz", size = "12345678" }
```

### `strip_components`

Number of directory components to strip when extracting archives:

```toml
[tools."s3:my-tool"]
version = "1.0.0"
url = "s3://my-bucket/tools/my-tool-v1.0.0.tar.gz"
strip_components = 1
```

::: info
If `strip_components` is not explicitly set, mise will automatically detect when to apply `strip_components = 1`. This happens when the extracted archive contains exactly one directory at the root level and no files.
:::

### `bin`

Rename the downloaded binary to a specific name. This is useful when downloading a single binary object that has a platform-specific name:

```toml
[tools."s3:my-tool"]
version = "1.0.0"
url = "s3://my-bucket/tools/my-tool-linux-x86_64"
bin = "my-tool"
```

::: info
When downloading single binaries (not archives), mise automatically removes OS/arch suffixes from the filename. For example, `my-tool-linux-x86_64` becomes `my-tool` automatically. Use the `bin` option only when you need a specific custom name.
:::

### `rename_exe`

Rename the executable after extraction from an archive. This is useful when the archive contains a binary with a platform-specific name that you want to rename:

```toml
[tools."s3:my-tool"]
version = "1.0.0"
url = "s3://my-bucket/tools/my-tool-v1.0.0-linux.zip"
rename_exe = "my-tool"
```

::: tip
Use `rename_exe` for archives where the binary inside has a different name than desired. Use `bin` for single binary downloads (not archives).
:::

### `bin_path`

Specify the directory containing binaries within the extracted archive:

```toml
[tools."s3:my-tool"]
version = "1.0.0"
url = "s3://my-bucket/tools/my-tool-v1.0.0.tar.gz"
bin_path = "my-tool-{{ version }}/bin"
```

### `format`

Explicitly specify the archive format when the URL lacks a file extension:

```toml
[tools."s3:my-tool"]
version = "1.0.0"
url = "s3://my-bucket/tools/my-tool-v1.0.0"
format = "tar.gz"
```

## Version Discovery

The S3 backend supports two methods for discovering available versions.

### Manifest File

Fetch available versions from a JSON manifest file stored in S3:

```toml
[tools."s3:my-tool"]
version = "latest"
url = "s3://my-bucket/tools/my-tool-v{{ version }}.tar.gz"
version_list_url = "s3://my-bucket/tools/versions.json"
```

The manifest file can be a JSON array of version strings:

```json
["1.0.0", "1.1.0", "2.0.0"]
```

Or a JSON array of objects (use `version_json_path` to extract versions):

```json
[{ "version": "1.0.0" }, { "version": "1.1.0" }, { "version": "2.0.0" }]
```

### `version_json_path`

Extract versions from JSON responses using a jq-like path expression:

```toml
[tools."s3:my-tool"]
version = "latest"
url = "s3://my-bucket/tools/my-tool-v{{ version }}.tar.gz"
version_list_url = "s3://my-bucket/tools/releases.json"
version_json_path = ".[].version"
```

### `version_expr`

Extract versions using an [expr-lang](https://expr-lang.org/) expression for complex version extraction logic:

```toml
[tools."s3:my-tool"]
version = "latest"
url = "s3://my-bucket/tools/my-tool-v{{ version }}.tar.gz"
version_list_url = "s3://my-bucket/tools/versions.txt"
version_expr = 'split(body, "\n")'
```

The expression receives the response body as the `body` variable and should return an array of version strings.

### S3 Object Listing

Discover versions by listing objects in the S3 bucket:

```toml
[tools."s3:my-tool"]
version = "latest"
url = "s3://my-bucket/tools/my-tool-v{{ version }}.tar.gz"
version_prefix = "tools/my-tool-v"
version_regex = "my-tool-v([0-9.]+)"
```

- `version_prefix`: The S3 key prefix to list objects from
- `version_regex`: A regular expression to extract version numbers from object keys (first capturing group is used)

## Custom Endpoint Example (MinIO)

Here's a complete example using MinIO as an S3-compatible backend:

```toml
[tools."s3:my-internal-tool"]
version = "latest"
url = "s3://tools-bucket/releases/my-tool-{{ version }}.tar.gz"
endpoint = "http://minio.internal:9000"
region = "us-east-1"
version_list_url = "s3://tools-bucket/releases/versions.json"
bin_path = "bin"
```

With environment variables:

```sh
export AWS_ACCESS_KEY_ID="minio-access-key"
export AWS_SECRET_ACCESS_KEY="minio-secret-key"
mise install
```

## Comparison with HTTP Backend

| Feature           | S3 Backend                                          | HTTP Backend      |
| ----------------- | --------------------------------------------------- | ----------------- |
| Authentication    | AWS credentials (env vars, ~/.aws/credentials, IAM) | HTTP auth headers |
| Version discovery | S3 listing or manifest file                         | HTTP endpoint     |
| Custom endpoints  | Yes (MinIO, etc.)                                   | N/A               |
| Use case          | Private/enterprise tools                            | Public downloads  |
