marten-s3 0.2.0

🔐 S3 file storage backend for the Marten framework

Marten S3

GitHub Release Specs QA

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.

Repository

marten-s3

Owner
Statistic
  • 3
  • 0
  • 0
  • 0
  • 4
  • 6 days ago
  • April 8, 2025
License

MIT License

Links
Synced at

Wed, 19 Aug 2026 16:50:29 GMT

Languages