diff --git a/app/client/components/create-repository-form.tsx b/app/client/components/create-repository-form.tsx index 120e0f6..40d4ffc 100644 --- a/app/client/components/create-repository-form.tsx +++ b/app/client/components/create-repository-form.tsx @@ -36,6 +36,7 @@ type Props = { const defaultValuesForType = { local: { backend: "local" as const, compressionMode: "auto" as const }, s3: { backend: "s3" as const, compressionMode: "auto" as const }, + r2: { backend: "r2" as const, compressionMode: "auto" as const }, gcs: { backend: "gcs" as const, compressionMode: "auto" as const }, azure: { backend: "azure" as const, compressionMode: "auto" as const }, rclone: { backend: "rclone" as const, compressionMode: "auto" as const }, @@ -115,6 +116,7 @@ export const CreateRepositoryForm = ({ Local S3 + Cloudflare R2 Google Cloud Storage Azure Blob Storage @@ -222,6 +224,67 @@ export const CreateRepositoryForm = ({ )} + {watchedBackend === "r2" && ( + <> + ( + + Endpoint + + + + R2 endpoint (without https://). Find in R2 dashboard under bucket settings. + + + )} + /> + ( + + Bucket + + + + R2 bucket name for storing backups. + + + )} + /> + ( + + Access Key ID + + + + R2 API token Access Key ID (create in Cloudflare R2 dashboard). + + + )} + /> + ( + + Secret Access Key + + + + R2 API token Secret Access Key (shown once when creating token). + + + )} + /> + + )} + {watchedBackend === "gcs" && ( <> { @@ -19,6 +20,7 @@ const encryptConfig = async (config: RepositoryConfig): Promise { return `${REPOSITORY_BASE}/${config.name}`; case "s3": return `s3:${config.endpoint}/${config.bucket}`; + case "r2": { + const endpoint = config.endpoint.replace(/^https?:\/\//, ''); + return `s3:${endpoint}/${config.bucket}`; + } case "gcs": return `gs:${config.bucket}:/`; case "azure": @@ -98,6 +102,12 @@ const buildEnv = async (config: RepositoryConfig) => { env.AWS_ACCESS_KEY_ID = await cryptoUtils.decrypt(config.accessKeyId); env.AWS_SECRET_ACCESS_KEY = await cryptoUtils.decrypt(config.secretAccessKey); break; + case "r2": + env.AWS_ACCESS_KEY_ID = await cryptoUtils.decrypt(config.accessKeyId); + env.AWS_SECRET_ACCESS_KEY = await cryptoUtils.decrypt(config.secretAccessKey); + env.AWS_REGION = "auto"; + env.AWS_S3_FORCE_PATH_STYLE = "true"; + break; case "gcs": { const decryptedCredentials = await cryptoUtils.decrypt(config.credentialsJson); const credentialsPath = path.join("/tmp", `gcs-credentials-${crypto.randomBytes(8).toString("hex")}.json`);