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
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
StorageProviderinterface (seesrc/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
TigrisStorageProviderCreate
src/server/storage/tigris-storage-provider.tsimplementing theStorageProviderinterface, modelled aftersrc/server/storage/r2-storage-provider.ts:The Tigris equivalent should:
https://fly.storage.tigris.devas the S3 endpoint (or allow it to be configurable).StorageProvidermethods:signUpload,signReadUrl,buildReadUrl,deleteObject.2. Update types
Extend
src/server/storage/types.tsto include Tigris:Add a
TigrisStorageCredentialtype mirroringR2StorageCredential(withoutaccountId, since Tigris doesn't require it):3. Update
config-resolver.tsUpdate
src/server/storage/config-resolver.tsto:readEnvTigrisStorageCredential()— readsTIGRIS_BUCKET,TIGRIS_ACCESS_KEY_ID,TIGRIS_SECRET_ACCESS_KEY,TIGRIS_PUBLIC_BASE_URLfrom env.resolveStorageConfig()to detect and return the appropriate provider based on which credentials are present (e.g.STORAGE_DRIVER=tigris).4. Update
provider.tsUpdate the provider factory/resolver to instantiate
TigrisStorageProviderwhenconfig.provider === "tigris".5. Update
src/lib/integration-providers.tsAdd a Tigris provider definition alongside
storageR2Provider:6. Update
src/server/api/routers/integration.tsAdd a
createTigrisClient()helper (analogous tocreateR2Client()) and wire it up for credential test/save flows.7. Update
src/server/api/routers/setup.tsUpdate the storage health check in
src/server/api/routers/setup.tsto support probing Tigris credentials in addition to R2.8. Update env
Update
src/env.jsto add Tigris environment variables:TIGRIS_BUCKETTIGRIS_ACCESS_KEY_IDTIGRIS_SECRET_ACCESS_KEYTIGRIS_PUBLIC_BASE_URLAlso update the
STORAGE_DRIVERenum to accept"tigris".9. Export from
src/server/storage/index.tsExport
TigrisStorageProviderandTigrisStorageCredentialfromsrc/server/storage/index.ts.10. Update docs
README.mdto documentSTORAGE_DRIVER=tigrisandTIGRIS_*env variables.docs/cloud-storage-deployment.mdto mention Tigris as a supported provider option alongside R2.Acceptance Criteria
TigrisStorageProviderimplements the fullStorageProviderinterface and passes equivalent tests toR2StorageProvider.STORAGE_DRIVER=tigriswithTIGRIS_*env variables works for self-hosted installs.