Skip to content

Request addressing & custom domains ​

TinyS3 supports both S3 request styles and per-bucket custom domains, so applications that need bucket-specific DNS endpoints work unchanged, with a certificate per domain.

Path-style (default) ​

https://<host>/<bucket>/<key> — always available, needs no configuration. The bucket is the first path segment.

Reserved bucket names ​

Because the bucket is the first path segment, a handful of top-level paths the server already serves for itself would collide with a bucket of the same name and be unreachable path-style. Those names are reserved — creating a bucket with one is rejected with 400 InvalidBucketName:

Reserved nameServes
consolethe web console UI (/console/)
restthe admin REST API (/rest/)
tinys3health & metrics endpoints (/tinys3/health/…, /tinys3/metrics)
mcpthe MCP server, only when the MCP plugin is loaded

Any additional plugin that registers a top-level route reserves its own name the same way while it is loaded. The reservation applies to both request styles. Virtual-host and custom-domain addressing are unaffected — a bucket reachable only as console.s3.example.com never collides with the path-style /console route, but the name is still reserved so the bucket stays reachable path-style too.

Virtual-host style ​

https://<bucket>.<domain>/<key> — the bucket is the left-most label of the Host header. This is what the AWS SDKs use by default, so enabling it lets a default-configured SDK talk to TinyS3 without forcePathStyle.

Turn it on by setting one or more base domains:

bash
# environment (comma-separated) base domains
TINY_S3_DOMAIN=s3.example.com,s3.internal
yaml
# or in config
server:
  domains: [s3.example.com]

With s3.example.com set, bucket.s3.example.com resolves to the bucket bucket; the bare s3.example.com stays path-style (so GET s3.example.com/ is ListBuckets). Only a single left-most label is treated as a bucket — a.b.s3.example.com is not routed as a bucket. Point wildcard DNS (*.s3.example.com) at the server. SigV4 is unaffected: the client signs the Host it sends, and the server verifies against it before resolving the bucket.

Custom domain per bucket ​

Map an arbitrary FQDN to a bucket so clients reach it as https://assets.example.com/logo.png — the domain replaces the bucket. Managed per bucket via ?customDomain (owner-only, like the other bucket-config sub-resources):

PUT    /<bucket>?customDomain     <CustomDomainConfiguration><Domain>assets.example.com</Domain></CustomDomainConfiguration>
GET    /<bucket>?customDomain
DELETE /<bucket>?customDomain

A domain can map to only one bucket (a second claim is rejected). Point that domain's DNS at the server and, for browser use, make the objects public (a public-read bucket policy) or sign requests.

If the bucket also has a website configuration, the mapped domain is served as a static website: https://<domain>/ resolves to the index document and missing keys return the error document. This Host-based website serving runs ahead of the console/REST routing, so / and /index.html on the mapped domain are the bucket's objects, not the console. Enabling a website grants no public access on its own — you still need a public-read policy (or signed requests). The bare API host is not a website endpoint; use the mapped domain. Mappings resolve in one storage read, cached briefly, and work identically on a single node or a cluster (they live in the quorum-replicated system store). A custom domain must not sit under a configured base domain — the base-domain wildcard claims all its subdomains as virtual-host buckets.

Per-domain TLS certificates (SNI) ​

Serve many domains, each with its own certificate, on one port — the certificate is chosen per connection from the TLS SNI hostname, with a default for anything unmatched:

yaml
server:
  tls:
    enabled: true
    certFile: /etc/tinys3/default.crt   # default (unmatched SNI)
    keyFile:  /etc/tinys3/default.key
    certs:
      - hosts: [assets.example.com]
        certFile: /etc/tinys3/assets.crt
        keyFile:  /etc/tinys3/assets.key
      - hosts: ["*.shop.example.com"]   # wildcards allowed
        certFile: /etc/tinys3/shop.crt
        keyFile:  /etc/tinys3/shop.key

Omit certs for the ordinary single-certificate setup.

TinyS3 is AGPLv3 licensed. Cloudflare and Cloudflare Workers are trademarks of Cloudflare, Inc. Amazon S3 and AWS are trademarks of Amazon.com, Inc. or its affiliates. MinIO is a trademark of MinIO, Inc. They are named only to describe compatibility; totis.ai is not affiliated with, endorsed by, or sponsored by any of them.