Skip to content

S3-compatible

The S3 provider talks to anything that speaks the S3 REST API — AWS S3, Cloudflare R2, Backblaze B2, Wasabi, MinIO, Storj, custom self-hosted endpoints. The SPA detects the major dialects and adjusts a couple of defaults automatically.

FieldExampleNotes
Endpoint URLhttps://s3.eu-west-1.amazonaws.comFull URL of the S3-compatible endpoint. For R2: https://<account>.r2.cloudflarestorage.com.
Regionus-east-1Some endpoints accept auto; others require an exact region (AWS, Wasabi).
Bucketmy-bucketMust already exist; the SPA does not create buckets.
Bucket path prefixwattcloudOptional. Vault root becomes s3://<bucket>/<prefix>/WattcloudVault/. Leave empty to place the vault at the bucket root.
Access Key IDAKIA…Stored on device, AES-GCM-wrapped, never sent to the relay.
Secret Access KeySame. Never logged, never persisted server-side.
Force path-style URLstoggleOn for MinIO and Backblaze B2; off for AWS, R2, Wasabi (auto-detected — override only when the detection guesses wrong).

When you paste an endpoint, the SPA checks the hostname and, if it matches, applies sensible defaults:

Endpoint shapeDetectedPath-style
*.r2.cloudflarestorage.comCloudflare R2off
s3.<region>.wasabisys.comWasabion
*.<your-host> (anything not above and matching MinIO patterns)MinIOon

Browsers refuse cross-origin S3 calls without an explicit CORS allowance on the bucket. If the connect step fails with a generic network error or “Unknown error”, the SPA flags this and shows a Copy CORS JSON button. The minimal rule is:

{
"CORSRules": [
{
"AllowedOrigins": ["*"],
"AllowedMethods": ["GET", "PUT", "HEAD", "DELETE"],
"AllowedHeaders": ["*"],
"ExposeHeaders": ["ETag"],
"MaxAgeSeconds": 3600
}
]
}

Tighten AllowedOrigins to your actual SPA origin in production (https://cloud.example.com).

  • AWS S3: bucket → PermissionsCross-origin resource sharing.
  • Cloudflare R2: bucket → SettingsCORS Policy.
  • MinIO: mc admin config set for the server, or front a reverse proxy that injects CORS headers.
  • Backblaze B2: Application Key UI → CORS rules attached to the bucket.
  • Wasabi: bucket → PropertiesPermissionsCORS.

The SPA only needs object-level access to the bucket (or the prefix you chose). For AWS, an inline policy looks like:

{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": ["s3:ListBucket"],
"Resource": "arn:aws:s3:::my-bucket",
"Condition": { "StringLike": { "s3:prefix": "wattcloud/*" } }
},
{
"Effect": "Allow",
"Action": ["s3:GetObject", "s3:PutObject", "s3:DeleteObject"],
"Resource": "arn:aws:s3:::my-bucket/wattcloud/*"
}
]
}

Drop the Condition and shorten the prefix if the vault sits at the bucket root. Cloudflare R2 and the other vendors expose equivalent controls; tune for the same surface.

The bucket’s own encryption settings (SSE-S3, SSE-KMS, R2 default encryption) are independent of Wattcloud’s. They do not weaken or strengthen Wattcloud’s V7 encryption — the bytes the SPA writes to the bucket are already AES-256-GCM ciphertext with a hybrid X25519 + ML-KEM-1024 key wrap. Server-side encryption on top is fine; turning it off doesn’t make anything readable to the bucket operator.

The vault writes V7 ciphertext objects sized to your file chunking (default chunk size around 1 MiB). Object listing happens on each folder-level navigation. For very large vaults on per-request-priced backends (B2, R2 free tier, Wasabi minimum object durations), this can add up — keep an eye on monthly object counts and request rates if you have hundreds of thousands of files.

  • WebDAV for file-level backends.
  • SFTP for SSH-reachable hosts.