Skip to content

DigitalOcean Spaces

DigitalOcean Spaces object storage for file uploads, avatars, and media. The extension registers a Spaces-backed implementation of the platform's FileStorageStrategy interface, deriving the S3-compatible endpoint from your Spaces region (https://<region>.digitaloceanspaces.com) and supporting an optional CDN URL for public objects. Core upload surfaces — avatar uploads, media uploads, presigned browser uploads, and the media-orphan purge — then read and write objects in your Space.

At a glance

Extension id digitalocean_spaces
Category storage
Version 0.1.0
Provides FileStorageStrategy implementation (registered as digitalocean_spaces)
External account DigitalOcean — Spaces access key + secret key

What It Provides

  • File storage strategyDigitalOceanSpacesStorageStrategy, registered with the strategy resolver as a FileStorageStrategy implementation named digitalocean_spaces when the extension activates, alongside the built-in local backend.
  • The FileStorageStrategy interface covers four operations: upload bytes under a key (returns the public URL), delete an object, build a browser-accessible public URL for a key, and generate a presigned upload URL.
  • The implementation wraps the shared S3Service (backend/vectis/core/s3.py): path-style requests ({endpoint}/{bucket}/{key}) signed with AWS Signature Version 4 over httpx — no boto3/aiobotocore dependency.
  • Nothing else — the package contributes no webhook endpoints, Temporal workflows, schedules, admin pages, GraphQL fields, or event subscriptions.

Setup

  1. Once installed (or dev-linked in development), the extension is discovered at startup. Enable it for a channel from Settings > Extensions (per-channel activation via ChannelExtension).
  2. Set the environment variables the manifest's install hint names: S3_REGION (e.g. nyc3), S3_ACCESS_KEY, S3_SECRET_KEY, S3_BUCKET.
  3. Restart the API. The strategy is constructed once, at extension activation, from those application settings.

Configuration Reference

Key Type Required Secret Description
s3_region string Yes No Spaces Region. Defaults to nyc3.
s3_access_key string Yes No Spaces Access Key
s3_secret_key password Yes Yes Spaces Secret Key
s3_bucket string Yes No Space Name
s3_public_url string No No CDN URL (optional)

password-typed fields are encrypted at rest (Fernet) and masked as *** in the admin configuration form.

Configuration is read from the environment, not the admin form

The activation hook builds the strategy from application settings (environment variables / .env) with the same key names uppercased — S3_REGION, S3_ACCESS_KEY, S3_SECRET_KEY, S3_BUCKET, S3_PUBLIC_URL. The extension defines no hot_reload hook, so values saved through the admin configuration form are stored but nothing hands them to the already-registered strategy. Configure via environment variables and restart.

Permissions

The manifest declares no admin permissions (permissions=[]), so no role assignment is needed.

Operational Notes

  • Who calls it — core resolves the active FileStorageStrategy at call time for avatar uploads (POST /api/upload/avatar), media uploads (POST /upload), presigned upload URLs (GET /upload/presign), CMS image derivative generation, and the daily vectis-gc-media-orphans Temporal schedule (GcMediaOrphansWorkflow), which physically deletes purged media objects through the active backend.
  • Which backend wins — every registered backend keeps its name (local, digitalocean_spaces, s3, ...); when core resolves the storage strategy without naming one, the most recently registered implementation is returned.
  • Endpoint — always derived from the region as https://<region>.digitaloceanspaces.com; unlike the Amazon S3 extension, there is no endpoint override.
  • Public URLs are <base>/<key>, where the base is the CDN URL (S3_PUBLIC_URL) when set, otherwise https://<bucket>.<region>.digitaloceanspaces.com.
  • Presigned uploadsgenerate_presigned_url returns a SigV4 query-string presigned PUT URL against the Spaces endpoint; the GET /upload/presign endpoint uses the default 3600-second expiry.
  • Uploads sign with UNSIGNED-PAYLOAD and a 60-second HTTP timeout; deletes treat a 404 as success (idempotent) with a 30-second timeout.
  • Avatar uploads fall back to the built-in local backend when the primary backend raises, so a misconfigured Space degrades rather than hard-fails that endpoint.
  • The three S3-compatible storage extensions — Amazon S3, MinIO, and DigitalOcean Spaces — all read the same S3_* settings; configure the one that matches your provider. See also Storage Extensions in the developer guide.