Trove

Configuration

Configure Trove via YAML files, programmatic options, or environment variables.

Trove supports three configuration sources that merge in a defined order: YAML files, programmatic options, and built-in defaults. This gives you full flexibility to configure storage in any environment.

YAML Configuration

Add a trove key under extensions in your Forge config file:

# config.yaml
extensions:
  trove:
    driver_dsn: "file:///data/storage"       # Storage driver DSN
    grove_database: "default"                # Named Grove DB from DI for metadata
    base_path: "/trove/v1"                   # HTTP route prefix
    disable_routes: false                    # Skip HTTP route registration
    disable_migrate: false                   # Skip auto-migration
    default_bucket: "default"                # Default bucket name
    cas_algorithm: "sha256"                  # CAS hash: sha256, blake3, xxhash

The extension also supports a top-level trove key for backward compatibility:

# Legacy format (still supported)
trove:
  driver_dsn: "s3://my-bucket?region=us-east-1"

The namespaced extensions.trove key is checked first. If not found, the extension falls back to the top-level trove key.

Multi-Store Configuration

Trove supports multiple named file stores, each with its own storage driver, metadata database, and settings. This mirrors how Grove supports multiple named databases.

extensions:
  trove:
    base_path: "/trove/v1"
    stores:
      - name: primary
        storage_driver: "s3://us-east-1/my-bucket"
        grove_database: "primary"
        default_bucket: "uploads"
        enable_compression: true
      - name: archive
        storage_driver: "file:///data/archive"
        grove_database: "archive-db"
        default_bucket: "archive"
      - name: temp
        storage_driver: "mem://"
        default_bucket: "scratch"
    default: primary

Store Entry Fields

FieldTypeDescription
namestringUnique identifier (required)
storage_driverstringDSN for the storage backend (required)
grove_databasestringNamed Grove DB for metadata
default_bucketstringDefault bucket name
enable_casboolEnable content-addressable storage
enable_encryptionboolAuto-configure encryption middleware
enable_compressionboolAuto-configure compression middleware

Default Store

The default field sets which store is used for unnamed DI injection (vessel.Inject[*trove.Trove]). If omitted, the first entry in stores becomes the default.

Validation

The configuration is validated during extension registration:

  • Each store must have a name and storage_driver
  • Store names must be unique
  • If default is set, it must reference an existing store name

Backward Compatibility

Single-store configuration (without the stores array) continues to work as before. The extension automatically detects whether to use single-store or multi-store mode based on whether stores is present.

Programmatic Options

Options set via troveext functions are merged with YAML configuration:

troveext.New(
    troveext.WithBasePath("/storage/v1"),
    troveext.WithConfig(troveext.Config{
        DriverDSN:     "file:///data/storage",
        DefaultBucket: "uploads",
        CASAlgorithm:  "blake3",
    }),
    troveext.WithDisableRoutes(),
    troveext.WithDisableMigrate(),
    troveext.WithGroveDatabase("analytics-db"),
)

Single-Store Options

FunctionDescription
troveext.WithBasePath(path)Set the HTTP route prefix
troveext.WithConfig(cfg)Provide a full troveext.Config struct
troveext.WithDisableRoutes()Skip HTTP route registration
troveext.WithDisableMigrate()Skip automatic database migration
troveext.WithGroveDatabase(name)Use a named Grove DB from DI for metadata
troveext.WithTroveOption(opt)Add a trove.Option applied during initialization
troveext.WithStore(s)Provide a pre-built metadata store

Multi-Store Options

FunctionDescription
troveext.WithFileStore(name, drv)Add a named store with a pre-configured driver
troveext.WithFileStoreDSN(name, dsn)Add a named store using a DSN string
troveext.WithDefaultFileStore(name)Set which named store is the default
troveext.WithTroveOptionFor(name, opt)Add a trove.Option scoped to a named store

Programmatic store entries take precedence over YAML entries with the same name.

Config Merge Behavior

Configuration sources merge in this order:

  1. YAML config -- extensions.trove key, then trove key
  2. Programmatic options -- Values set via option functions
  3. Defaults -- Built-in fallback values

YAML values take precedence over programmatic values for the same field. Programmatic values fill in anything YAML does not set. Boolean flags like disable_routes are additive: if either source sets it to true, it stays true.

Driver DSN Reference

The driver_dsn (or storage_driver in multi-store entries) field determines which storage backend Trove uses. Each driver is identified by a URI scheme:

DriverDSN FormatExample
Local filesystemfile:///pathfile:///data/storage
Local filesystemlocal://./relative/pathlocal://./storages/local
In-memorymem://mem://
Amazon S3s3://bucket?region=...&endpoint=...s3://my-bucket?region=us-east-1
Google Cloud Storagegs://bucketgs://my-bucket
Azure Blob Storageazblob://containerazblob://my-container
SFTPsftp://user@host/pathsftp://user@storage.example.com/data

The local driver accepts both file:// (absolute paths) and local:// (relative paths) schemes. Relative paths are resolved from the current working directory.

S3-compatible stores (MinIO, DigitalOcean Spaces, Backblaze B2) use the s3:// scheme with the endpoint query parameter:

driver_dsn: "s3://my-bucket?region=us-east-1&endpoint=https://minio.local:9000"

Driver Registry

Storage drivers register themselves in a global registry via their init() function. When Trove resolves a DSN, it extracts the scheme and looks up the corresponding driver factory. The following drivers are auto-registered when imported:

PackageRegistered Scheme(s)
drivers/localdriverfile, local
drivers/memdrivermem
drivers/s3drivers3
drivers/gcsdrivergcs
drivers/azuredriverazure
drivers/sftpdriversftp

In multi-store mode, ensure you import the driver packages your stores need so their init() functions register the factories.

Grove Database

The grove_database field tells Trove which Grove database instance to use for its metadata tables (buckets, objects, uploads, CAS index, quotas).

  • If grove_database is set, Trove resolves a named Grove DB: vessel.InjectNamed[*grove.DB](container, name)
  • If omitted or set to "default", Trove uses the default Grove DB: vessel.Inject[*grove.DB](container)

This lets you run Trove metadata on a dedicated database separate from your application data by pointing grove_database at a named Grove database entry.

In multi-store mode, each store can reference a different Grove database. This keeps metadata isolated between stores.

Environment Variables

DSN values and other configuration strings can reference environment variables in your YAML config. This is handled by Forge's config loader:

extensions:
  trove:
    driver_dsn: "${TROVE_DRIVER_DSN}"
    grove_database: "${TROVE_GROVE_DB:-default}"

This keeps secrets out of config files and lets you vary configuration across environments without changing YAML.

On this page