marten-s3 0.2.0
Marten S3
Marten S3 provides an Amazon S3 file storage backend for the Marten web framework. It works with AWS S3 and S3-compatible services such as MinIO, Wasabi, or Cloudflare R2.
Installation
Simply add the following entry to your project's shard.yml:
dependencies:
marten_s3:
github: martenframework/marten-s3
And run shards install afterward.
Configuration
First, add the following requirement to your project's src/project.cr file:
require "marten_s3"
Then add the application to your project's installed apps (usually in config/settings/base.cr) and assign the storage to media_files.storage (typically in config/settings/production.cr):
Marten.configure do |config|
config.installed_apps = [
MartenS3::App,
# …
]
config.media_files.storage = MartenS3::Store.new(
region: ENV.fetch("S3_REGION"),
bucket: ENV.fetch("S3_BUCKET"),
access_key: ENV.fetch("S3_ACCESS_KEY"),
secret_key: ENV.fetch("S3_SECRET_KEY"),
)
end
The same store can also be used for collected assets by assigning it to assets.storage.
You should ensure that access keys are kept secret and that they are not hardcoded in your config files.
Constructor arguments
| Argument | Required | Default | Description |
|---|---|---|---|
region |
yes | — | AWS region (or a placeholder region for compatible services). |
bucket |
yes | — | Name of the bucket used to persist files. |
access_key |
yes | — | Access key ID. |
secret_key |
yes | — | Secret access key. |
endpoint |
no | nil |
Custom endpoint URL. Required for non-AWS S3-compatible services. |
force_path_style |
no | false |
Use path-style URLs (endpoint/bucket/key) instead of virtual-hosted-style URLs (bucket.endpoint/key). Required for most compatible providers. |
expires_in |
no | 86400 |
Lifetime of generated presigned URLs, in seconds. |
public_urls |
no | false |
Generate public object URLs instead of presigned URLs. Use this when objects are publicly readable. |
S3-compatible services
For MinIO, Wasabi, and similar providers, set a custom endpoint and enable force_path_style:
Marten.configure do |config|
config.media_files.storage = MartenS3::Store.new(
region: ENV.fetch("S3_REGION", "us-east-1"),
bucket: ENV.fetch("S3_BUCKET"),
access_key: ENV.fetch("S3_ACCESS_KEY"),
secret_key: ENV.fetch("S3_SECRET_KEY"),
endpoint: ENV.fetch("S3_ENDPOINT"),
force_path_style: true,
)
end
Public URLs
By default, #url returns a time-limited presigned URL. If objects in the bucket are publicly readable, set public_urls: true to generate unsigned URLs instead:
MartenS3::Store.new(
region: ENV.fetch("S3_REGION"),
bucket: ENV.fetch("S3_BUCKET"),
access_key: ENV.fetch("S3_ACCESS_KEY"),
secret_key: ENV.fetch("S3_SECRET_KEY"),
public_urls: true,
)
Custom S3 client
If you already have an Awscr::S3::Client instance, you can pass it directly to the store:
client = Awscr::S3::Client.new(
ENV.fetch("S3_REGION"),
ENV.fetch("S3_ACCESS_KEY"),
ENV.fetch("S3_SECRET_KEY"),
)
config.media_files.storage = MartenS3::Store.new(client, ENV.fetch("S3_BUCKET"))
Authors
Marvin Ahlgrimm (@treagod) and contributors.
License
MIT. See LICENSE for more details.
marten-s3
- 3
- 0
- 0
- 0
- 4
- 6 days ago
- April 8, 2025
MIT License
Wed, 19 Aug 2026 16:50:29 GMT