storage

S3

The S3-compatible driver, a separately versioned module built on minio-go.

storage/driver/s3 is the production driver: an S3-compatible Driver built on minio-go. It's a separate Go module, not a subpackage of the root storage module: it has its own go.mod and its own version, because it pulls in minio-go as a real dependency, and only the projects that actually talk to S3 should carry that weight. Everything else in storage (Disk, Manager, the decorators, storage/memory, storage/local) has no idea this module exists.

Install

go get github.com/gp-system/storage/driver/s3@latest

This is versioned independently from github.com/gp-system/storage itself: bumping the root module doesn't require bumping this one, and vice versa. Both are required in go.mod, since the driver imports the root module's types (Driver, FileInfo, and so on).

Config

import "github.com/gp-system/storage/driver/s3"

cfg := s3.Config{ /* ... */ }
driver, err := s3.New(cfg)
disk := storage.NewDisk(driver, storage.WithName("s3"))

Compose s3.Config into your project config under an S3_ prefix, the same way any gpsystem module's config composes:

type Config struct {
    // ...
    Storage s3.Config `envPrefix:"S3_"`
}
VariableDefaultMeaning
S3_ENDPOINTrequiredthe service address (s3.amazonaws.com, a MinIO host, ...)
S3_REGIONus-east-1
S3_BUCKETrequired
S3_ACCESS_KEY / S3_SECRET_KEYemptycredentials for the endpoint
S3_USE_PATH_STYLEfalsetrue for most self-hosted S3 (/bucket/key addressing instead of virtual-host-style)
S3_PUBLIC_BASE_URLemptybase for Disk.URL (a CDN, or the bucket's own public endpoint)

The full list lives in the configuration reference.

Not just AWS

Because the driver is built on minio-go rather than the AWS SDK, it speaks to any service implementing the S3 API, not only AWS itself: AWS S3, MinIO, RustFS, Cloudflare R2, and Backblaze B2 all work behind the same s3.Config, generally just by pointing S3_ENDPOINT and S3_USE_PATH_STYLE at the right values. A project generated with new project already runs a self-hosted, S3-compatible rustfs service in its dev compose.yml, so local development never needs real AWS credentials.

// Client is an escape hatch for anything the Driver interface doesn't expose
client := driver.Client() // *minio.Client
bucket := driver.Bucket() // the configured bucket name

s3.New also accepts options; WithTransport(http.RoundTripper) lets you swap the underlying HTTP transport, useful for custom TLS configuration or for injecting an OTel-instrumented transport of your own.

Presigned URLs

TemporaryURL and TemporaryUploadURL are implemented with minio-go's native presigning (PresignedGetObject/PresignedPutObject): the returned URL points directly at the S3-compatible endpoint, so the client downloads or uploads without the request passing through your service at all. This is the same Driver contract every other driver implements, so code that calls disk.TemporaryURL(...) doesn't know or care that it's talking to S3 rather than the local driver's HMAC-signed links.

Standalone example

main.go
package main

import (
    "context"
    "log"
    "strings"
    "time"

    "github.com/gp-system/storage"
    "github.com/gp-system/storage/driver/s3"
)

func main() {
    driver, err := s3.New(s3.Config{
        Endpoint:      "localhost:9000",
        Region:        "us-east-1",
        Bucket:        "uploads",
        AccessKey:     "minioadmin",
        SecretKey:     "minioadmin",
        UsePathStyle:  true,
        PublicBaseURL: "http://localhost:9000/uploads",
    })
    if err != nil {
        log.Fatal(err)
    }
    disk := storage.NewDisk(driver, storage.WithName("s3"))

    ctx := context.Background()
    if err := disk.Put(ctx, "hello.txt", strings.NewReader("hello, s3"), storage.PutOptions{}); err != nil {
        log.Fatal(err)
    }

    signed, err := disk.TemporaryURL(ctx, "hello.txt", storage.TemporaryURLOptions{TTL: 15 * time.Minute})
    if err != nil {
        log.Fatal(err)
    }
    log.Println("presigned link:", signed)
}
  • Overview: the Driver/Disk/Manager model this driver plugs into.
  • Disk API: the methods Disk exposes over any driver, including this one.
  • Memory and local disk: the drivers for tests and single-server deployments.
  • Testing: run the conformance suite against your own S3-compatible endpoint.
  • External dependencies: the minio-go version this driver pins.
Copyright © 2026