Skip to content

feat: Add Tigris as a storage provider #41

Description

@babblebey

Add support for Tigris as a storage provider, alongside the existing Cloudflare R2 integration. Tigris is an S3-compatible globally distributed object storage service, so the implementation should closely mirror how R2 is supported today.

Background

The storage layer is already well-abstracted behind a StorageProvider interface (see src/server/storage/). Cloudflare R2 is currently the only supported provider. Tigris is also S3-compatible and should integrate cleanly using the same AWS SDK S3 client.

Tasks

1. Add TigrisStorageProvider

Create src/server/storage/tigris-storage-provider.ts implementing the StorageProvider interface, modelled after src/server/storage/r2-storage-provider.ts:

// src/server/storage/r2-storage-provider.ts
export class R2StorageProvider implements StorageProvider {
  public readonly driver = "r2" as const;

  public constructor(config: R2StorageCredential) {
    const { accountId, bucket, accessKeyId, secretAccessKey } = config;
    this.client = new S3Client({
      region: "auto",
      endpoint: `https://${accountId}.r2.cloudflarestorage.com`,
      // ...
    });
  }
  // signUpload, signReadUrl, buildReadUrl, deleteObject
}

The Tigris equivalent should:

  • Use https://fly.storage.tigris.dev as the S3 endpoint (or allow it to be configurable).
  • Implement all StorageProvider methods: signUpload, signReadUrl, buildReadUrl, deleteObject.

2. Update types

Extend src/server/storage/types.ts to include Tigris:

// Before
export type StorageDriver = "r2";
export type StorageCredentialProvider = "r2";

// After
export type StorageDriver = "r2" | "tigris";
export type StorageCredentialProvider = "r2" | "tigris";

Add a TigrisStorageCredential type mirroring R2StorageCredential (without accountId, since Tigris doesn't require it):

export type TigrisStorageCredential = {
  bucket: string;
  accessKeyId: string;
  secretAccessKey: string;
  publicBaseUrl: string;
};

3. Update config-resolver.ts

Update src/server/storage/config-resolver.ts to:

  • Add readEnvTigrisStorageCredential() — reads TIGRIS_BUCKET, TIGRIS_ACCESS_KEY_ID, TIGRIS_SECRET_ACCESS_KEY, TIGRIS_PUBLIC_BASE_URL from env.
  • Update resolveStorageConfig() to detect and return the appropriate provider based on which credentials are present (e.g. STORAGE_DRIVER=tigris).

4. Update provider.ts

Update the provider factory/resolver to instantiate TigrisStorageProvider when config.provider === "tigris".

5. Update src/lib/integration-providers.ts

Add a Tigris provider definition alongside storageR2Provider:

// src/lib/integration-providers.ts
export const storageTigrisProvider: ProviderDef = {
  category: "storage",
  provider: "tigris",
  label: "Tigris",
  description: "Globally distributed S3-compatible object storage by Tigris",
  fields: [
    { name: "bucket", label: "Bucket Name", type: "text", required: true, ... },
    { name: "accessKeyId", label: "Access Key ID", type: "text", required: true, ... },
    { name: "secretAccessKey", label: "Secret Access Key", type: "password", required: true, ... },
    { name: "publicBaseUrl", label: "Public Base URL", type: "text", required: true, ... },
  ],
};

6. Update src/server/api/routers/integration.ts

Add a createTigrisClient() helper (analogous to createR2Client()) and wire it up for credential test/save flows.

7. Update src/server/api/routers/setup.ts

Update the storage health check in src/server/api/routers/setup.ts to support probing Tigris credentials in addition to R2.

8. Update env

Update src/env.js to add Tigris environment variables:

  • TIGRIS_BUCKET
  • TIGRIS_ACCESS_KEY_ID
  • TIGRIS_SECRET_ACCESS_KEY
  • TIGRIS_PUBLIC_BASE_URL

Also update the STORAGE_DRIVER enum to accept "tigris".

9. Export from src/server/storage/index.ts

Export TigrisStorageProvider and TigrisStorageCredential from src/server/storage/index.ts.

10. Update docs

  • Update README.md to document STORAGE_DRIVER=tigris and TIGRIS_* env variables.
  • Update docs/cloud-storage-deployment.md to mention Tigris as a supported provider option alongside R2.

Acceptance Criteria

  • TigrisStorageProvider implements the full StorageProvider interface and passes equivalent tests to R2StorageProvider.
  • Tigris appears as an option in Settings > Integrations under Storage.
  • Credential test/save flow works for Tigris in both cloud mode and self-hosted mode.
  • STORAGE_DRIVER=tigris with TIGRIS_* env variables works for self-hosted installs.
  • Existing R2 behaviour is unaffected.
  • Docs are updated.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Fields

    No fields configured for Feature.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions