> ## Documentation Index
> Fetch the complete documentation index at: https://docs.fly.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Tigris Global Object Storage

[Tigris](https://tigrisdata.com) is a globally distributed, multi-cloud object storage service with built-in support for the S3 API. Tigris is available natively as the object storage provider for Fly.io.

<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/cn2if9oInK0?si=LcWG4wle9DBBPf4F" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen />

<br />

Objects in Tigris are stored close to the region where they're written. Then, when requested, objects are replicated close to the requesting user. This durable cross-region replication is intelligently managed by Tigris based on global traffic patterns. This automatic global replication can replace a CDN and makes all your data available at low latency with zero configuration required.

Learn more from their [service overview](https://www.tigrisdata.com/docs/overview/) and [architecture docs](https://www.tigrisdata.com/docs/concepts/architecture/).

## Use Tigris with your framework

Language- and framework-specific guides for setting up Tigris:

* [Rails with Active Storage](/rails/the-basics/active-storage)
* [Laravel with Tigris for CDN File Storage](/laravel/the-basics/laravel-tigris-file-storage)
* [JavaScript with S3Client](/js/the-basics/object-storage)

## Create and manage a Tigris storage bucket

Provision Tigris storage buckets through the [Fly CLI](/flyctl/install). Install it, then [sign up for a Fly account](/getting-started/sign-up-sign-in). Once provisioned, you can also manage your buckets and objects with the [Tigris CLI](https://www.tigrisdata.com/docs/cli/) or any S3-compatible SDK — see [Connect to your bucket](#connect-to-your-bucket) below.

<Info>
  Running the following command in a Fly.io app context -- inside an app directory or specifying `-a yourapp` -- will automatically set secrets on your app.
</Info>

<CodeGroup>
  ```bash cmd theme={null}
  fly storage create
  ```

  ```output output theme={null}
  ? Select Organization: fly-ephemeral (fly-ephemeral)
  ? Choose a name, use the default, or leave blank to generate one:
  Your project (summer-grass-2004) is ready.

  Set one or more of the following secrets on your target app.
  BUCKET_NAME: summer-grass-2004
  AWS_ENDPOINT_URL_S3: https://fly.storage.tigris.dev
  AWS_ACCESS_KEY_ID: tid_xxxxxx
  AWS_SECRET_ACCESS_KEY: tsec_xxxxxx
  ```
</CodeGroup>

### Public buckets

By default, buckets are private. If you need to serve public assets like images or JavaScript files, create a *public bucket*:

```bash theme={null}
fly storage create --public
```

You can also make a public bucket private.

```bash theme={null}
fly storage update mybucket --private
```

Objects in a public bucket can be accessed by anyone without authentication. Public content is served from dedicated domains using the bucket name as a subdomain:

* `https://mybucket.t3.tigrisfiles.io/key-name` (primary)
* `https://mybucket.t3.tigrisbucket.io/key-name`
* `https://mybucket.t3.tigrisblob.io/key-name`

No credentials or pre-signed URLs are needed. For production use, we recommend setting up a custom domain so your public URLs stay stable:

```bash theme={null}
flyctl storage update mybucket --custom-domain assets.example.com
```

Then create a CNAME record for `assets.example.com` pointing to `mybucket.t3.tigrisbucket.io`. See the [Tigris Custom Domain docs](https://www.tigrisdata.com/docs/buckets/custom-domain/) for full setup instructions and the [Tigris Public Bucket docs](https://www.tigrisdata.com/docs/buckets/public-bucket/) for details on all available public domains.

### Object Level Access Control

By default, all objects inherit the access control settings of the bucket they are in. If a bucket is private, all objects in it are also private and vice versa.
However, you can make individual objects in a bucket public-read (or private) by setting an object level ACL on them. This lets you serve a public object from an otherwise private bucket, or a private object from an otherwise public bucket.
For details on how to set this up see the [Tigris Object ACL docs](https://www.tigrisdata.com/docs/objects/acl/)

### Access keys

`fly storage create` prints a Tigris access key ID and secret in its output (and sets them as `AWS_ACCESS_KEY_ID` / `AWS_SECRET_ACCESS_KEY` secrets on your Fly app, when run in an app context). Save them at that moment — `flyctl` can't retrieve them later, and `fly secrets list` only shows hashes.

To view or create new keys for an existing bucket, open the Tigris web console with `fly storage dashboard <bucket-name>` and manage keys there. For Tigris CLI use, the [Tigris CLI](#tigris-cli) sidesteps raw keys via `tigris login`.

### The Tigris web console

The [Tigris web console](https://console.storage.dev) at `console.storage.dev` is a visual interface for managing buckets, objects, access keys, and usage. From a Fly account, open it either way:

* Click the **Tigris Object Storage** tab in the [Fly Dashboard](https://fly.io/dashboard).
* Run `flyctl storage dashboard <bucket_name>` from the command line to jump to a specific bucket, or `flyctl storage dashboard --org <org_name>` for the organization-level overview (billing, organization settings).

If you visit `console.storage.dev` directly, the Tigris sign-in page offers two paths:

* **Sign in with Fly.io** — choose **Fly.io** on the Tigris login page to manage buckets created through `fly storage create`. Tigris reads your Fly organization, so the buckets shown match `flyctl storage list`.
* **Sign in directly** — Tigris also supports standalone accounts (Google, GitHub, or email). These are independent of any Fly account and only see buckets created under that Tigris account.

### List your buckets

Get a list of all of your Tigris buckets.

<CodeGroup>
  ```bash cmd theme={null}
  flyctl storage list
  ```

  ```output output theme={null}
  NAME                  	ORG
  js-storage-1           	fly-ephemeral
  late-surf-5384        	fly-ephemeral
  ```
</CodeGroup>

Or with the [Tigris CLI](#tigris-cli) (see [setup below](#tigris-cli)):

```bash theme={null}
tigris buckets list
```

### Delete a Tigris bucket

Deleting a bucket permanently deletes the bucket and all of its objects. This can't be undone. `fly storage destroy` asks for confirmation; use `--yes` to skip the prompt in automation.

<CodeGroup>
  ```bash cmd theme={null}
  fly storage destroy late-surf-5384
  ```

  ```output output theme={null}
  Destroying a Tigris bucket is not reversible.
  ? Destroy Tigris bucket late-surf-5384? Yes
  Your Tigris bucket late-surf-5384 was destroyed
  ```
</CodeGroup>

Or with the [Tigris CLI](#tigris-cli):

```bash theme={null}
tigris buckets delete late-surf-5384
```

## Connect to your bucket

Buckets created with `fly storage create` are standard Tigris buckets. You can manage them three ways:

* **`flyctl`** — for bucket lifecycle (create, list, destroy) and shadow buckets.
* **[Tigris CLI](https://www.tigrisdata.com/docs/cli/)** — for day-to-day bucket and object management, plus Tigris-specific features like snapshots, forks, and shadow buckets.
* **S3-compatible SDKs** — for application code in any language.

All three target the same bucket and accept the credentials that `fly storage create` set on your Fly app.

### Endpoint

The canonical Tigris S3 endpoint is `https://t3.storage.dev`. We recommend using it for new code.

`fly storage create` currently sets the `AWS_ENDPOINT_URL_S3` secret on your Fly app to `https://fly.storage.tigris.dev`. Both endpoints reach the same Tigris service and the same buckets, so existing code keeps working. To switch a Fly app to the canonical endpoint:

```bash theme={null}
fly secrets set AWS_ENDPOINT_URL_S3=https://t3.storage.dev
```

To configure an SDK or tool manually:

* **Endpoint URL:** `https://t3.storage.dev`
* **Region:** `auto`
* **Access key ID:** from `AWS_ACCESS_KEY_ID`
* **Secret access key:** from `AWS_SECRET_ACCESS_KEY`

### Tigris CLI

The [Tigris CLI](https://www.tigrisdata.com/docs/cli/) (`tigris`, also available as `t3`) manages Tigris buckets and objects from the command line. It targets `https://t3.storage.dev` by default.

Install and sign in:

```bash theme={null}
npm install -g @tigrisdata/cli
tigris login
```

When prompted, choose **As a user (OAuth2 flow)**, then select **Fly.io** on the login page that opens in your browser. This connects the CLI to buckets created through your Fly account. Then run commands like:

```bash theme={null}
tigris ls
tigris cp ./photo.jpg t3://my-bucket/photo.jpg
tigris presign t3://my-bucket/photo.jpg
```

### Tigris SDKs

Tigris is S3-compatible, so any AWS SDK works — point it at `https://t3.storage.dev`. Tigris publishes language-specific guides for [Python](https://www.tigrisdata.com/docs/sdks/s3/aws-python-sdk/), [Node.js](https://www.tigrisdata.com/docs/sdks/s3/aws-js-sdk/), [Go](https://www.tigrisdata.com/docs/sdks/s3/aws-go-sdk/), [Ruby](https://www.tigrisdata.com/docs/sdks/s3/aws-ruby-sdk/), [PHP](https://www.tigrisdata.com/docs/sdks/s3/aws-php-sdk/), [.NET](https://www.tigrisdata.com/docs/sdks/s3/aws-net-sdk/), [Java](https://www.tigrisdata.com/docs/sdks/s3/aws-java-sdk/), and [Elixir](https://www.tigrisdata.com/docs/sdks/s3/aws-elixir-sdk/).

### Snapshots and forks

[Snapshots and forks](https://www.tigrisdata.com/docs/buckets/snapshots-and-forks/) are Tigris-only features that aren't exposed through `flyctl`.

* **Snapshots** are point-in-time references to a bucket's state. When snapshots are enabled, Tigris persists every write to the bucket, so the bucket's full history is restorable — not just the moments you took a manual snapshot. `tigris snapshots take` simply names a point in time for easy reference.
* **Forks** are copy-on-write clones of a bucket from a chosen snapshot. Writes to a fork don't affect the source bucket, so they're useful for testing migrations, branching production data, or running experiments on isolated copies.

Snapshots must be enabled when the bucket is created — they cannot be turned on later, and forks require snapshots. Buckets created with `fly storage create` do not have snapshots enabled.

To use snapshots and forks on Fly-provisioned buckets, install the [Tigris CLI](https://www.tigrisdata.com/docs/cli/) and sign in with your Fly.io account:

```bash theme={null}
npm install -g @tigrisdata/cli
tigris login
```

When prompted, choose **As a user (OAuth2 flow)**, then select **Fly.io** on the login page that opens in your browser. The CLI then manages every Tigris bucket on your Fly account — `tigris buckets list` should show the same buckets as `flyctl storage list`.

Snapshots can't be enabled on existing buckets, so create a new bucket with the `--enable-snapshots` flag, then migrate or write data into it:

```bash theme={null}
tigris buckets create my-bucket --enable-snapshots
tigris snapshots take my-bucket
tigris forks create my-bucket my-fork
```

You can also create snapshot-enabled buckets from a [Tigris SDK](https://www.tigrisdata.com/docs/sdks/) or the [Tigris web console](https://console.storage.dev).

## Migrate from another S3-compatible provider with zero downtime

Tigris supports **zero-downtime, lazy migration** from any S3-compatible storage provider — AWS S3, Cloudflare R2, Google Cloud Storage, MinIO, Backblaze B2, and others. Instead of copying everything up front, Tigris fetches objects from your old bucket as your application requests them and asynchronously stores copies in Tigris for future reads. Only data that's actually used moves over, so migration latency and egress costs stay low.

The migration setup uses a **shadow bucket**: your existing source bucket, attached to a Tigris bucket through `flyctl`. Once attached, your application points at Tigris, and Tigris transparently fills in objects from the shadow bucket as needed. See the [Tigris migration guide](https://www.tigrisdata.com/docs/migration/) for provider-specific setup.

### How shadow bucket migration works

* **Reads:** Tigris checks its own bucket first. On a miss, it fetches the object from the shadow bucket, returns it to the caller, and asynchronously copies it into Tigris (in a region close to the user). Subsequent reads are served from Tigris with no shadow lookup.
* **Writes (default):** Objects are written only to Tigris.
* **Writes (write-through enabled):** Objects are written to both Tigris and the shadow bucket simultaneously, keeping both stores in sync.
* **Deletes:** Removed from both Tigris and the shadow bucket.
* **Listing:** With write-through enabled, `ListObjects` returns the full shadow bucket contents. Without write-through, only objects already migrated into Tigris are listed.

### Write-through mode: zero-downtime cutover

Write-through mode (the `--shadow-write-through` flag below) is what makes the migration zero-downtime and reversible. Because every new write also lands in your old bucket, your previous provider stays fully current while you run on Tigris in production. You can soak in this dual-write state for days, weeks, or months, validate behavior, and roll back to your old provider at any time without data loss. When you're ready, disable write-through and decommission the old bucket.

### Create a new bucket with a shadow bucket

You must specify all five shadow bucket attributes: bucket name, access key, secret key, endpoint, and region. Check your provider docs to find these values. Here's the AWS S3 [list of regions and endpoints](https://docs.aws.amazon.com/general/latest/gr/s3.html).

```bash theme={null}
flyctl storage create -n mybucket -o myorg --shadow-name source-bucket --shadow-access-key 123 --shadow-secret-key abc --shadow-endpoint https://s3.us-east-1.amazonaws.com --shadow-region us-east-1 --shadow-write-through
```

### Add or remove a shadow bucket on an existing Tigris bucket

You can also add and remove shadow buckets from existing Tigris buckets.

```bash theme={null}
flyctl storage update mybucket --shadow-name source-bucket --shadow-access-key 123 --shadow-secret-key abc --shadow-endpoint https://s3.us-east-1.amazonaws.com --shadow-region us-east-1

flyctl storage update mybucket --clear-shadow
```

`--shadow-write-through` enables zero-downtime cutover by replicating every new write back to the source bucket.

## Pricing and Billing

Tigris buckets created through your Fly account are billed through Fly. Tigris usage appears on your regular Fly bill — there's no separate Tigris invoice or account to manage. This applies whether you create buckets with `fly storage create`, the Tigris CLI, or a Tigris SDK using the credentials Fly provisioned for you.

Buckets are billed by usage with no up-front costs. Check the official [Tigris Pricing](https://www.tigrisdata.com/docs/pricing/) page for rates.

## AWS API compatibility

Check out the Tigris docs on compatibility: [https://www.tigrisdata.com/docs/api/s3](https://www.tigrisdata.com/docs/api/s3)

Tigris also supports the following:

* [Pre-signed URLs](https://docs.aws.amazon.com/AmazonS3/latest/userguide/using-presigned-url.html) for secure download and upload
* Setting HTTP headers on objects such as `Cache-Control`
