config

package
v0.2.5 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 3, 2026 License: MIT Imports: 16 Imported by: 0

README

Configuration Package

The config package provides flexible configuration options for the simple-content server, supporting both programmatic (functional options) and environment variable configuration patterns.

Quick Start

Environment Variables (12-Factor App Style)
# Basic configuration
export PORT="8080"
export ENVIRONMENT="production"
export DATABASE_TYPE="postgres"
export DATABASE_URL="postgresql://user:pass@localhost/db"

# Filesystem storage
export FS_BASE_DIR="./data/storage"
export FS_URL_PREFIX="http://localhost:8080/api/v1"
export FS_SIGNATURE_SECRET_KEY="$(openssl rand -hex 32)"
export DEFAULT_STORAGE_BACKEND="fs"

# URL strategy
export URL_STRATEGY="storage-delegated"

# Run server
./server-configured
Programmatic Configuration
package main

import (
    "log"
    "github.com/tendant/simple-content/pkg/simplecontent/config"
)

func main() {
    cfg, err := config.Load(
        config.WithPort("8080"),
        config.WithEnvironment("production"),
        config.WithDatabase("postgres", "postgresql://user:pass@localhost/db"),
        config.WithFilesystemStorage("fs", "./data/storage", "/api/v1", "secret-key"),
        config.WithDefaultStorage("fs"),
        config.WithStorageDelegatedURLs(),
    )
    if err != nil {
        log.Fatal(err)
    }

    svc, err := cfg.BuildService()
    if err != nil {
        log.Fatal(err)
    }

    // Use service...
}

Configuration Patterns

Pattern 1: Pure Environment Variables

Best for containerized deployments (Docker, Kubernetes):

# .env file
PORT=8080
ENVIRONMENT=production
DATABASE_TYPE=postgres
DATABASE_URL=postgresql://localhost/mydb
FS_BASE_DIR=/var/data/storage
DEFAULT_STORAGE_BACKEND=fs
cfg, err := config.LoadServerConfig() // Uses WithEnv("") internally
Pattern 2: Pure Programmatic

Best for libraries, testing, and embedded usage:

cfg, err := config.Load(
    config.WithPort("8080"),
    config.WithDatabase("memory", ""),
    config.WithMemoryStorage(""),
    config.WithDefaultStorage("memory"),
    config.WithContentBasedURLs("/api/v1"),
)
Pattern 3: Mixed (Programmatic + Environment Overrides)

Best for development with production parity:

cfg, err := config.Load(
    // Set sensible defaults programmatically
    config.WithPort("8080"),
    config.WithDatabase("postgres", "postgresql://localhost/dev"),
    config.WithFilesystemStorage("fs", "./data", "/api/v1", "dev-secret"),
    config.WithDefaultStorage("fs"),

    // Allow environment variables to override
    config.WithEnv(""),
)

Available Options

Server Options
WithPort
config.WithPort("8080")

Sets the HTTP server port.

WithEnvironment
config.WithEnvironment("production")  // or "development", "testing"

Sets the runtime environment.

Database Options
WithDatabase
// Memory (for testing)
config.WithDatabase("memory", "")

// PostgreSQL
config.WithDatabase("postgres", "postgresql://user:pass@host/db")

Configures the database backend.

WithDatabaseSchema
config.WithDatabaseSchema("content")  // Default schema for Postgres

Sets the PostgreSQL schema name.

Storage Backend Options
WithMemoryStorage
config.WithMemoryStorage("")  // Name defaults to "memory"
config.WithMemoryStorage("test-storage")  // Custom name

Adds an in-memory storage backend (useful for testing).

WithFilesystemStorage
config.WithFilesystemStorage(
    "fs",                    // Backend name
    "./data/storage",        // Base directory
    "/api/v1",              // URL prefix for presigned URLs
    "your-secret-key",      // HMAC secret key (empty = unsigned URLs)
)

Adds a filesystem storage backend.

Full configuration:

config.WithFilesystemStorageFull(
    "fs",                    // Backend name
    "./data/storage",        // Base directory
    "/api/v1",              // URL prefix
    "secret-key",           // HMAC secret
    1800,                   // Presigned URL expiry (seconds)
)
WithS3Storage
config.WithS3Storage(
    "s3",           // Backend name
    "my-bucket",    // S3 bucket
    "us-west-2",    // AWS region
)

Adds an S3 storage backend.

With credentials:

config.WithS3Storage("s3", "my-bucket", "us-west-2"),
config.WithS3Credentials("s3", "AKIAIOSFODNN7EXAMPLE", "wJalrXUt..."),

With custom endpoint (MinIO, LocalStack):

config.WithS3Storage("s3", "my-bucket", "us-east-1"),
config.WithS3Endpoint(
    "s3",
    "http://localhost:9000",  // MinIO endpoint
    false,                    // useSSL
    true,                     // usePathStyle (required for MinIO)
),

Full configuration:

config.WithS3StorageFull(
    "s3",                            // Backend name
    "my-bucket",                     // Bucket
    "us-west-2",                     // Region
    "AKIAIOSFODNN7EXAMPLE",         // Access key
    "wJalrXUt...",                  // Secret key
    "http://localhost:9000",         // Endpoint (MinIO)
    false,                           // useSSL
    true,                            // usePathStyle
)
WithDefaultStorage
config.WithDefaultStorage("fs")  // Use filesystem as default

Sets which storage backend to use by default.

URL Strategy Options
WithContentBasedURLs
config.WithContentBasedURLs("/api/v1")

Routes all upload/download requests through the application server:

  • Upload: /api/v1/contents/{id}/upload
  • Download: /api/v1/contents/{id}/download

Use when: Simple development setup, full control over access.

WithStorageDelegatedURLs
config.WithStorageDelegatedURLs()

Delegates URL generation to storage backends (presigned URLs):

  • Upload: /api/v1/upload/{objectKey}?signature=...&expires=...
  • Download: /api/v1/download/{objectKey}?signature=...&expires=...

Use when: Using filesystem or S3 presigned URLs with HMAC authentication.

WithCDNURLs
config.WithCDNURLs(
    "https://cdn.example.com",      // CDN base URL (for downloads)
    "https://api.example.com",      // Upload base URL
)

Hybrid strategy: CDN for downloads, application for uploads.

Use when: Production with CDN in front of storage.

Advanced Options
WithObjectKeyGenerator
config.WithObjectKeyGenerator("git-like")  // Default, recommended
config.WithObjectKeyGenerator("tenant-aware")
config.WithObjectKeyGenerator("high-performance")
config.WithObjectKeyGenerator("legacy")

Sets the object key generation strategy.

WithEventLogging
config.WithEventLogging(true)   // Enable
config.WithEventLogging(false)  // Disable

Enables or disables event logging.

WithPreviews
config.WithPreviews(true)

Enables or disables preview generation.

WithAdminAPI
config.WithAdminAPI(true)

Enables or disables admin API endpoints.

Complete Examples

Development Setup
cfg, err := config.Load(
    config.WithPort("8080"),
    config.WithEnvironment("development"),
    config.WithDatabase("memory", ""),
    config.WithFilesystemStorage("fs", "./data/storage", "/api/v1", "dev-secret"),
    config.WithDefaultStorage("fs"),
    config.WithContentBasedURLs("/api/v1"),
    config.WithObjectKeyGenerator("git-like"),
    config.WithEventLogging(true),
    config.WithPreviews(true),
    config.WithAdminAPI(true),
)
Production with PostgreSQL and Filesystem
cfg, err := config.Load(
    config.WithPort("8080"),
    config.WithEnvironment("production"),
    config.WithDatabase("postgres", os.Getenv("DATABASE_URL")),
    config.WithDatabaseSchema("content"),
    config.WithFilesystemStorageFull(
        "fs",
        "/var/data/storage",
        "https://api.example.com",
        os.Getenv("FS_SECRET_KEY"),
        1800,  // 30 minutes
    ),
    config.WithDefaultStorage("fs"),
    config.WithStorageDelegatedURLs(),
    config.WithObjectKeyGenerator("git-like"),
    config.WithEventLogging(true),
    config.WithPreviews(true),
    config.WithAdminAPI(false),
)
Production with S3
cfg, err := config.Load(
    config.WithPort("8080"),
    config.WithEnvironment("production"),
    config.WithDatabase("postgres", os.Getenv("DATABASE_URL")),
    config.WithS3StorageFull(
        "s3",
        os.Getenv("S3_BUCKET"),
        os.Getenv("AWS_REGION"),
        os.Getenv("AWS_ACCESS_KEY_ID"),
        os.Getenv("AWS_SECRET_ACCESS_KEY"),
        "",     // No custom endpoint
        true,   // useSSL
        false,  // usePathStyle
    ),
    config.WithDefaultStorage("s3"),
    config.WithCDNURLs(
        "https://cdn.example.com",
        "https://api.example.com",
    ),
    config.WithObjectKeyGenerator("git-like"),
)
Testing Configuration
cfg, err := config.Load(
    config.WithPort("0"),  // Random port
    config.WithEnvironment("testing"),
    config.WithDatabase("memory", ""),
    config.WithMemoryStorage(""),
    config.WithDefaultStorage("memory"),
    config.WithContentBasedURLs("/api/v1"),
    config.WithEventLogging(false),
    config.WithPreviews(false),
)

Environment Variable Reference

Server
  • PORT - Server port (default: "8080")
  • ENVIRONMENT - Runtime environment (default: "development")
Database
  • DATABASE_TYPE - Database backend: "memory", "postgres" (default: "memory")
  • DATABASE_URL - Database connection URL (required for postgres)
  • DATABASE_SCHEMA - PostgreSQL schema name (default: "content")
Filesystem Storage
  • FS_BASE_DIR - Base directory for files (required to enable FS backend)
  • FS_URL_PREFIX - URL prefix for presigned URLs (optional)
  • FS_SIGNATURE_SECRET_KEY - HMAC secret key for signed URLs (optional)
  • FS_PRESIGN_EXPIRES_SECONDS - Presigned URL expiry in seconds (default: 3600)
S3 Storage
  • S3_BUCKET - S3 bucket name (required to enable S3 backend)
  • S3_REGION - AWS region (default: "us-east-1")
  • S3_ACCESS_KEY_ID - AWS access key ID
  • S3_SECRET_ACCESS_KEY - AWS secret access key
  • S3_ENDPOINT - Custom S3 endpoint (for MinIO, LocalStack)
  • S3_USE_SSL - Use SSL for S3 connections (default: true)
  • S3_USE_PATH_STYLE - Use path-style URLs (required for MinIO)
  • S3_PRESIGN_DURATION - Presigned URL duration in seconds (default: 3600)
URL Strategy
  • URL_STRATEGY - URL generation strategy: "content-based", "cdn", "storage-delegated" (default: "content-based")
  • CDN_BASE_URL - CDN base URL (required for CDN strategy)
  • UPLOAD_BASE_URL - Upload base URL (for CDN hybrid mode)
  • API_BASE_URL - API base URL (for content-based strategy, default: "/api/v1")
Advanced
  • DEFAULT_STORAGE_BACKEND - Default storage backend name (default: "memory")
  • OBJECT_KEY_GENERATOR - Object key generator: "git-like", "tenant-aware", "legacy" (default: "git-like")
  • ENABLE_EVENT_LOGGING - Enable event logging (default: true)
  • ENABLE_PREVIEWS - Enable preview generation (default: true)
  • ENABLE_ADMIN_API - Enable admin API endpoints (default: false)

Best Practices

Use Environment Variables for Secrets
// ✅ Good - secrets from environment
cfg, err := config.Load(
    config.WithDatabase("postgres", os.Getenv("DATABASE_URL")),
    config.WithS3Credentials("s3",
        os.Getenv("AWS_ACCESS_KEY_ID"),
        os.Getenv("AWS_SECRET_ACCESS_KEY"),
    ),
)

// ❌ Bad - secrets in code
cfg, err := config.Load(
    config.WithDatabase("postgres", "postgresql://user:pass@localhost/db"),
)
Layer Configuration Sources
// 1. Start with sensible defaults
cfg, err := config.Load(
    config.WithPort("8080"),
    config.WithEnvironment("development"),

    // 2. Apply application-specific config
    config.WithDatabase("postgres", "postgresql://localhost/dev"),
    config.WithFilesystemStorage("fs", "./data", "/api/v1", ""),

    // 3. Allow environment overrides
    config.WithEnv(""),
)
Validate Configuration Early
cfg, err := config.Load(/* options */)
if err != nil {
    log.Fatalf("Invalid configuration: %v", err)
}

// Validate database connection
if cfg.DatabaseType == "postgres" {
    if err := config.PingPostgres(cfg.DatabaseURL, cfg.DBSchema); err != nil {
        log.Fatalf("Database connection failed: %v", err)
    }
}

Migration from Environment-Only Configuration

If you're currently using only environment variables:

// Before (environment-only)
cfg, err := config.LoadServerConfig()

// After (same behavior, more explicit)
cfg, err := config.Load(config.WithEnv(""))

// Or with programmatic defaults + env overrides
cfg, err := config.Load(
    config.WithPort("8080"),
    config.WithDatabase("postgres", "postgresql://localhost/dev"),
    config.WithEnv(""),  // Env vars override programmatic config
)

No breaking changes - existing environment variable configuration continues to work!

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func PingPostgres added in v0.1.1

func PingPostgres(databaseURL, schema string) error

PingPostgres verifies connectivity to Postgres and optionally sets search_path for the session. It fails if the schema (when provided) does not exist.

Types

type Option added in v0.1.7

type Option func(*ServerConfig) error

Option applies configuration to a ServerConfig instance.

func WithAdminAPI added in v0.1.28

func WithAdminAPI(enabled bool) Option

WithAdminAPI enables or disables the admin API endpoints

func WithCDNURLs added in v0.1.28

func WithCDNURLs(cdnBaseURL, uploadBaseURL string) Option

WithCDNURLs configures CDN URL strategy with hybrid upload support

func WithContentBasedURLs added in v0.1.28

func WithContentBasedURLs(apiBaseURL string) Option

WithContentBasedURLs configures content-based URL strategy

func WithDatabase added in v0.1.28

func WithDatabase(dbType, url string) Option

WithDatabase configures the database backend

func WithDatabaseSchema added in v0.1.28

func WithDatabaseSchema(schema string) Option

WithDatabaseSchema sets the database schema (for Postgres)

func WithDefaultStorage added in v0.1.28

func WithDefaultStorage(name string) Option

WithDefaultStorage sets the default storage backend name

func WithDefaults added in v0.1.28

func WithDefaults() Option

WithDefaults is a convenience option that applies sensible defaults This is useful as a base before applying more specific options

func WithEnv added in v0.1.7

func WithEnv(prefix string) Option

WithEnv applies environment variable overrides using the provided prefix.

Simplified environment variable mapping:

Server (cmd/server-configured only):

PORT - Server port (default: "8080")
ENVIRONMENT - Runtime environment (default: "development")

Database:

DATABASE_URL - Connection string (e.g., "postgresql://user:pass@host/db")
               If set with "postgresql://" prefix, automatically sets DATABASE_TYPE=postgres
               If empty or "memory", uses in-memory database

Storage:

STORAGE_URL - Storage connection string (one of):
              - "memory://" - In-memory storage (default)
              - "file:///path/to/data" - Filesystem storage
              - "s3://bucket?region=us-east-1" - S3 storage

That's it! Use programmatic config for advanced features.

func WithEnvironment added in v0.1.28

func WithEnvironment(env string) Option

WithEnvironment sets the environment (development, production, testing)

func WithEventLogging added in v0.1.28

func WithEventLogging(enabled bool) Option

WithEventLogging enables or disables event logging

func WithFilesystemStorage added in v0.1.28

func WithFilesystemStorage(name, baseDir, urlPrefix, secretKey string) Option

WithFilesystemStorage adds a filesystem storage backend If name is empty, defaults to "fs"

func WithFilesystemStorageExpiry added in v0.1.28

func WithFilesystemStorageExpiry(name string, expirySeconds int) Option

WithFilesystemStorageExpiry sets the presigned URL expiry for filesystem storage

func WithFilesystemStorageFull added in v0.1.28

func WithFilesystemStorageFull(name, baseDir, urlPrefix, secretKey string, expirySeconds int) Option

WithFilesystemStorageFull provides all filesystem storage configuration in one call

func WithMemoryStorage added in v0.1.28

func WithMemoryStorage(name string) Option

WithMemoryStorage adds a memory storage backend (for testing) If name is empty, defaults to "memory"

func WithObjectKeyGenerator added in v0.1.28

func WithObjectKeyGenerator(generator string) Option

WithObjectKeyGenerator sets the object key generation strategy Valid values: "git-like", "tenant-aware", "high-performance", "legacy"

func WithPort added in v0.1.28

func WithPort(port string) Option

WithPort sets the server port

func WithPreviews added in v0.1.28

func WithPreviews(enabled bool) Option

WithPreviews enables or disables preview generation

func WithS3Credentials added in v0.1.28

func WithS3Credentials(name, accessKeyID, secretAccessKey string) Option

WithS3Credentials sets AWS credentials for S3 storage

func WithS3Endpoint added in v0.1.28

func WithS3Endpoint(name, endpoint string, useSSL, usePathStyle bool) Option

WithS3Endpoint sets a custom S3 endpoint (for MinIO, LocalStack, etc.)

func WithS3PresignDuration added in v0.1.28

func WithS3PresignDuration(name string, durationSeconds int) Option

WithS3PresignDuration sets the presigned URL duration for S3 (in seconds)

func WithS3Storage added in v0.1.28

func WithS3Storage(name, bucket, region string) Option

WithS3Storage adds an S3 storage backend If name is empty, defaults to "s3"

func WithS3StorageFull added in v0.1.28

func WithS3StorageFull(name, bucket, region, accessKey, secretKey, endpoint string, useSSL, usePathStyle bool) Option

WithS3StorageFull provides all S3 storage configuration in one call

func WithStorageDelegatedURLs added in v0.1.28

func WithStorageDelegatedURLs() Option

WithStorageDelegatedURLs configures storage-delegated URL strategy This delegates URL generation to the storage backends (e.g., presigned S3/FS URLs)

type ServerConfig

type ServerConfig struct {
	ServiceConfig

	// Server-specific configuration
	Port           string
	Environment    string // development, production, testing
	EnableAdminAPI bool   // Enable admin API endpoints (requires authentication in production)
}

ServerConfig represents server configuration for the simple-content HTTP server (cmd/server-configured) This extends ServiceConfig with server-specific settings

func Load added in v0.1.7

func Load(opts ...Option) (*ServerConfig, error)

Load constructs a ServerConfig by applying the supplied options on top of library defaults.

func LoadServerConfig

func LoadServerConfig() (*ServerConfig, error)

LoadServerConfig is a convenience function that loads configuration from environment variables. It applies the default config and then overlays environment variable settings.

func (*ServerConfig) BuildRepository added in v0.1.15

func (c *ServerConfig) BuildRepository() (simplecontent.Repository, error)

BuildRepository builds just the repository from configuration This is a convenience method that delegates to ServiceConfig.BuildRepository()

func (*ServerConfig) BuildService

func (c *ServerConfig) BuildService() (simplecontent.Service, error)

BuildService creates a Service instance from the server configuration This is a convenience method that delegates to ServiceConfig.BuildService()

func (*ServerConfig) Validate

func (c *ServerConfig) Validate() error

Validate validates the server configuration (includes service validation + server-specific checks)

type ServiceConfig added in v0.1.28

type ServiceConfig struct {
	// Database configuration
	DatabaseURL  string
	DatabaseType string // "memory", "postgres"
	DBSchema     string // Postgres schema to use (default: content)

	// Storage configuration
	DefaultStorageBackend string
	StorageBackends       []StorageBackendConfig

	// Service options
	EnableEventLogging bool
	EnablePreviews     bool

	// URL generation
	URLStrategy   string // "cdn", "content-based", "storage-delegated"
	CDNBaseURL    string // Base URL for CDN strategy downloads (e.g., "https://cdn.example.com")
	UploadBaseURL string // Base URL for CDN strategy uploads (e.g., "https://api.example.com" or "/api/v1")
	APIBaseURL    string // Base URL for content-based strategy (e.g., "/api/v1")

	// Object key generation
	ObjectKeyGenerator string // "default", "git-like", "tenant-aware", "legacy"
}

ServiceConfig represents service-level configuration for the simple-content library This is the core configuration used by applications embedding the library

func (*ServiceConfig) BuildRepository added in v0.1.28

func (c *ServiceConfig) BuildRepository() (simplecontent.Repository, error)

BuildRepository builds just the repository from configuration

func (*ServiceConfig) BuildService added in v0.1.28

func (c *ServiceConfig) BuildService() (simplecontent.Service, error)

BuildService creates a Service instance from the service configuration

func (*ServiceConfig) Validate added in v0.1.28

func (c *ServiceConfig) Validate() error

Validate validates the service configuration

type StorageBackendConfig

type StorageBackendConfig struct {
	Name   string
	Type   string // "memory", "fs", "s3"
	Config map[string]interface{}
}

StorageBackendConfig represents configuration for a storage backend

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL