Storage providers
A Provider is one configured object-storage backend inside a Workspace. Clients discover Provider IDs through provider/list; endpoints, regions, addressing mode, and credentials remain server-side configuration.
Provider type
Section titled “Provider type”type selects the server implementation. Omitting it selects generic.
| Type | Connection | Behavior |
|---|---|---|
generic |
Explicit S3 endpoint | Standard S3 operations. |
aws |
Endpoint derived from the Region | Standard S3 with AWS bucket-location rules. |
minio |
Explicit MinIO S3 endpoint | Currently the same standard operations as generic. |
azure |
Native Blob service endpoint | Containers and blobs through the Azure API, using a SAS token. |
The server does not infer the type from a Provider ID, display name, or hostname.
Unknown types are configuration errors. The previous s3-compatible spelling
remains accepted as an alias for generic; config show writes generic.
Selecting a type does not guarantee that every operation is supported or
permitted. generic does not disable standard tagging or search operations.
minio does not currently enable a separate search implementation.
Google Cloud Storage and Hetzner use generic. Azure Blob Storage uses azure; an Azure-backed S3 gateway can still use generic.
Custom provider images
Section titled “Custom provider images”Set icon_path on any Provider to replace its built-in icon:
workspace: providers: - id: amazon-s3 display_name: Amazon S3 type: aws icon_path: /etc/s3lens/images/company.svg region: eu-west-1 credentials: access_key_id: ${AWS_ACCESS_KEY_ID} secret_access_key: ${AWS_SECRET_ACCESS_KEY}The path names a file on the server. Relative paths resolve from the server’s
working directory, including when configuration files are merged. Set the path
directly in the configuration. Environment references are not expanded for
icon_path. Remote URLs are not supported.
PNG, JPEG, GIF, WebP, and SVG files are supported. Each file must be nonempty and at most 256 KiB; all provider images together must fit within 1 MiB. A missing, unreadable, oversized, or unsupported file prevents server startup and identifies the affected Provider. The server reads images at startup, so restart it after changing an image.
The server returns the image as iconDataUrl in provider/list, only for Providers
the caller can see. Filesystem paths stay on the server. The web and desktop apps
use the custom image in the provider table, switcher, and provider page. Omitting
icon_path preserves the built-in icon selected by type.
Amazon S3
Section titled “Amazon S3”Use type: aws when the AWS SDK should derive the service endpoint from the Region:
workspace: id: production display_name: Production providers: - id: amazon-s3 display_name: Amazon S3 type: aws region: ${AWS_REGION:-eu-west-1} credentials: access_key_id: ${AWS_ACCESS_KEY_ID} secret_access_key: ${AWS_SECRET_ACCESS_KEY} session_token: ${AWS_SESSION_TOKEN:-}An AWS Provider does not accept a custom endpoint. Use generic for an S3 service with an explicit endpoint.
S3-compatible services
Section titled “S3-compatible services”workspace: id: self-hosted display_name: Self-hosted storage providers: - id: storage display_name: Storage type: generic endpoint: https://s3.example.com region: us-east-1 force_path_style: true credentials: access_key_id: ${S3_ACCESS_KEY_ID} secret_access_key: ${S3_SECRET_ACCESS_KEY}The endpoint must be an HTTP or HTTPS base URL without embedded credentials, query parameters, or a fragment. force_path_style: true is common for self-hosted services whose DNS does not provide virtual-hosted Bucket names.
For MinIO, use type: minio with the same connection fields. Both types require
an endpoint and a signing Region. Omitting type does not infer AWS or its endpoint.
Google Cloud Storage
Section titled “Google Cloud Storage”Google’s XML API interoperability accepts S3 signatures with Cloud Storage HMAC credentials. Use examples/google/provider.yaml with GCS_ACCESS_KEY_ID and GCS_SECRET_ACCESS_KEY, then run pnpm run dev -- --with google.
The endpoint is https://storage.googleapis.com, the signing region is auto, and path-style addressing supports dotted bucket names. These are HMAC keys, not service-account JSON keys or OAuth tokens. A service-account HMAC key uses its parent project by default. For user HMAC keys, set the default project under Cloud Storage Settings > Interoperability. S3 Lens does not send an explicit project header.
The generic adapter uses the XML API operations. S3 object tags and S3 bucket-policy documents have no documented XML API equivalent. Google IAM policies, labels, and resource tags are separate concepts. Tag-dependent searches can fail on this provider. region signs requests; it does not place a new bucket. Set optional bucket_location to select a Cloud Storage location when creating buckets, or omit it to use Google’s default.
Hetzner Object Storage
Section titled “Hetzner Object Storage”Use examples/hetzner/provider.yaml with HETZNER_ACCESS_KEY_ID, HETZNER_SECRET_ACCESS_KEY, and HETZNER_LOCATION, then run pnpm run dev -- --with hetzner.
The fixture defaults to fsn1 and uses https://fsn1.your-objectstorage.com. Configure one provider per location and project. The location selects both the endpoint and bucket_location, which the generic adapter sends as CreateBucketConfiguration.LocationConstraint. Existing generic configurations that omit bucket_location still send no location constraint. AWS rejects this field because its bucket location follows its region.
Hetzner documents S3 compatibility limits, including unsupported bucket tagging and cross-bucket copies that can fail even within one location. Such provider errors remain errors; S3 Lens does not silently replace a failed copy with a different operation. See Hetzner’s connection guide.
Azure Blob Storage
Section titled “Azure Blob Storage”workspace: providers: - id: azure display_name: Azure Blob Storage type: azure endpoint: https://${AZURE_STORAGE_ACCOUNT}.blob.core.windows.net credentials: sas_token: ${AZURE_STORAGE_SAS_TOKEN}examples/azure/provider.yaml contains this fragment. Export its variables and run pnpm run dev -- --with azure. Supply the Blob service endpoint without a SAS query. The token belongs in credentials.sas_token, with or without its leading ?; diagnostic configuration output redacts it. Azure rejects S3 configuration fields such as region, force_path_style, and access keys.
This integration currently accepts SAS authentication. It does not acquire Entra tokens or accept storage account keys or connection strings. An account SAS with Blob service access and the needed service, container, and object resource types supports account-wide browsing. Container and object SAS tokens cannot list the account’s containers. Grant only the operations required: listing, reading, creating or writing, deleting, and tags use their corresponding SAS permissions. Exact version deletion requires the version-delete permission. Expired or insufficient tokens return provider errors.
Azure containers appear as buckets, and blobs appear as objects. The adapter supports container discovery, lookup and creation, paginated object listing with folder delimiters, reads and previews, uploads, object deletion, tags, versions, and copy or move operations. Azure version IDs remain opaque. Version pagination resumes after a named version within the original provider page; a removed resume version produces an invalid-cursor error. Azure soft-deleted blobs and snapshots are not represented as S3 delete markers.
Streamed uploads stage 4 MiB blocks and commit only after the received byte count matches the declared length. The adapter supports at most 50,000 blocks, about 195 GiB per streamed upload. Interrupted uploads can leave uncommitted blocks for Azure to expire. Same-provider copies use synchronous Put Blob From URL, with a 5,000 MiB source limit and a condition that prevents overwriting an existing destination. Copies preserve blob tags and require SAS tag permission. A failed copy leaves the source in place.
The following operations return unsupportedOperation:
- Bucket deletion. Azure deletes a container and all its blobs, with no atomic empty-container condition matching S3 bucket deletion. Delete containers through Azure’s own tools.
- S3 bucket policies and policy-derived public-access status. Azure IAM and container access policies use different models.
- S3 multipart-upload discovery, part inspection, and abort. Azure’s uncommitted blocks do not provide the same upload-session contract.
For local verification, pnpm run dev -- --none --with azurite starts the pinned Azurite emulator with public development credentials. Azurite does not cover every cloud operation, including blob versions and Put Blob From URL. Successful local checks do not establish compatibility with every Azure account setting.
Included local fixtures
Section titled “Included local fixtures”The repository includes ready-to-run fixtures that pnpm run dev starts by name:
| Fixture | S3 endpoint | Start command |
|---|---|---|
| Garage | http://127.0.0.1:3900 |
pnpm run dev (default) |
| SeaweedFS | http://127.0.0.1:8333 |
pnpm run dev -- --with seaweedfs |
| RustFS | http://127.0.0.1:9000 |
pnpm run dev -- --with rustfs |
| VersityGW | http://127.0.0.1:7070 |
pnpm run dev -- --with versitygw |
| MinIO (legacy) | http://127.0.0.1:9000 |
pnpm run dev -- --with minio |
| Azurite | http://127.0.0.1:10000/s3lens |
pnpm run dev -- --with azurite |
| Google Cloud Storage | https://storage.googleapis.com |
pnpm run dev -- --with google |
| Hetzner | Location-specific S3 endpoint | pnpm run dev -- --with hetzner |
| Azure Blob Storage | Account-specific Blob endpoint | pnpm run dev -- --with azure |
| Amazon S3 | AWS | pnpm run dev -- --with aws |
| Cloudflare R2 | https://<account>.r2.cloudflarestorage.com |
pnpm run dev -- --with r2 |
Amazon S3 and Cloudflare R2 have no container; they read real credentials from the environment (S3LENS_DEVELOPMENT_AWS_*, and R2_ACCOUNT_ID plus R2_ACCESS_KEY_ID / R2_SECRET_ACCESS_KEY). MinIO and RustFS share port 9000, so the runner refuses to start them together. The MinIO community project is archived; its fixture is retained as a compatibility target, not as a production recommendation.
Each storage fixture under examples/ contains a provider.yaml fragment; local services also have a Compose file that is merged after examples/base.yaml. Validate and run one without the runner:
docker compose -f examples/compose.yaml up -d seaweedfscargo run -- config validate --config examples/base.yaml --config examples/seaweedfs/provider.yamlcargo run -- serve --config examples/base.yaml --config examples/seaweedfs/provider.yamlProvider credentials
Section titled “Provider credentials”Provider credentials authorize the S3 Lens server against the storage backend. They are separate from S3 Lens authentication and policies. Scope access keys to only the operations and Buckets the deployment needs.
Depending on enabled features, S3 Lens uses listing, get, put, copy, delete, tagging, versioning, multipart-upload, and native Bucket-policy operations. A Provider can accept the connection while rejecting individual operations that it does not implement or that the access key cannot perform; those failures are returned as stable protocol errors without leaking Provider diagnostics.