Skip to content

Configuration

Stowry uses a YAML configuration file with environment variable overrides.

Configuration values are loaded in this order (later sources override earlier ones):

  1. Default values
  2. Configuration file (config.yaml)
  3. Environment variables (STOWRY_ prefix)
  4. Command-line flags
# Server configuration
server:
port: 5708 # HTTP server port (default: 5708)
mode: store # Server mode: store, static, spa (default: store)
max_upload_size: 0 # Max upload size in bytes, 0 = unlimited (default: 0)
error_document: "" # Custom 404 page path for static mode (default: built-in)
# Service configuration
service:
cleanup_timeout: 30 # Cleanup operation timeout in seconds (default: 30)
# Database configuration
database:
type: sqlite # Database type: sqlite, postgres (default: sqlite)
dsn: stowry.db # Connection string or file path
tables:
meta_data: stowry_metadata # Metadata table name (default: stowry_metadata)
# Storage configuration
storage:
path: ./data # Directory for file storage (default: ./data)
# Authentication configuration
auth:
read: public # Read access: public, private (default: public)
write: public # Write access: public, private (default: public)
aws:
region: us-east-1 # AWS region for signature verification
service: s3 # AWS service name (default: s3)
keys:
inline: # Inline key definitions
- access_key: AKIAIOSFODNN7EXAMPLE
secret_key: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
# file: /path/to/keys.json # Or load from JSON file
# Logging
log:
level: info # Log level: debug, info, warn, error (default: info)
OptionTypeDefaultDescription
portint5708HTTP server port
modestringstoreServer mode (store, static, spa)
max_upload_sizeint0Maximum upload size in bytes (0 = unlimited)
error_documentstring""Custom 404 page path for static/SPA modes (empty = built-in HTML)
OptionTypeDefaultDescription
cleanup_timeoutint30Cleanup operation timeout in seconds
OptionTypeDefaultDescription
typestringsqliteDatabase type (sqlite requires 3.24+, postgres)
dsnstringstowry.dbConnection string
tables.meta_datastringstowry_metadataMetadata table name (lowercase, alphanumeric with underscores, max 63 chars)

Migration Options:

  1. CLI migration (recommended): Run stowry init before starting the server
  2. Manual SQL: Execute the schema SQL below directly in your database
-- Table name must be lowercase, alphanumeric with underscores, max 63 chars
CREATE TABLE IF NOT EXISTS stowry_metadata (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
path TEXT NOT NULL UNIQUE,
content_type TEXT NOT NULL,
etag TEXT NOT NULL,
file_size_bytes BIGINT NOT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
deleted_at TIMESTAMPTZ,
cleaned_up_at TIMESTAMPTZ
);
CREATE INDEX IF NOT EXISTS idx_stowry_metadata_deleted_at
ON stowry_metadata (deleted_at)
WHERE (deleted_at IS NOT NULL);
CREATE INDEX IF NOT EXISTS idx_stowry_metadata_pending_cleanup
ON stowry_metadata (deleted_at, cleaned_up_at)
WHERE (deleted_at IS NOT NULL AND cleaned_up_at IS NULL);
CREATE INDEX IF NOT EXISTS idx_stowry_metadata_active_list
ON stowry_metadata (created_at, path)
WHERE (deleted_at IS NULL);
-- Table name must be lowercase, alphanumeric with underscores, max 63 chars
CREATE TABLE IF NOT EXISTS stowry_metadata (
id TEXT NOT NULL PRIMARY KEY,
path TEXT NOT NULL UNIQUE,
content_type TEXT NOT NULL,
etag TEXT NOT NULL,
file_size_bytes INTEGER NOT NULL,
created_at TEXT NOT NULL,
updated_at TEXT NOT NULL,
deleted_at TEXT,
cleaned_up_at TEXT
);
CREATE INDEX IF NOT EXISTS idx_stowry_metadata_deleted_at
ON stowry_metadata (deleted_at);
CREATE INDEX IF NOT EXISTS idx_stowry_metadata_pending_cleanup
ON stowry_metadata (deleted_at, cleaned_up_at);
CREATE INDEX IF NOT EXISTS idx_stowry_metadata_active_list
ON stowry_metadata (created_at, path);

SQLite DSN Examples:

dsn: stowry.db # File-based database
dsn: :memory: # In-memory (testing only)
dsn: /var/lib/stowry/db # Absolute path

PostgreSQL DSN Examples:

dsn: postgres://user:password@localhost:5432/stowry
dsn: postgres://user:password@localhost:5432/stowry?sslmode=disable
dsn: host=localhost port=5432 user=stowry password=secret dbname=stowry
OptionTypeDefaultDescription
pathstring./dataDirectory for file storage

The storage directory is created automatically with 0o700 permissions (owner-only access). For Kubernetes deployments with shared access needs, pre-create the directory with 0o750 and use fsGroup in securityContext. Files are organized by their path, maintaining the original directory structure.

OptionTypeDefaultDescription
readstringpublicRead access mode (public, private)
writestringpublicWrite access mode (public, private)
aws.regionstringus-east-1AWS region for signature verification
aws.servicestrings3AWS service name
keys.inlinelist[]Inline list of access key pairs
keys.filestring-Path to JSON file containing keys

Note: The access control matrix below applies to store mode only. In static and spa modes, all access is public and write operations return 405 Method Not Allowed.

Access Control Matrix:

readwriteGETPUTDELETE
publicpublicPublicPublicPublic
publicprivatePublicAuth requiredAuth required
privateprivateAuth requiredAuth requiredAuth required
privatepublicAuth requiredPublicPublic

Multiple Keys (inline):

auth:
read: private
write: private
keys:
inline:
- access_key: KEY1
secret_key: SECRET1
- access_key: KEY2
secret_key: SECRET2

Keys from file:

auth:
keys:
file: /path/to/keys.json

Where keys.json contains:

[
{"access_key": "KEY1", "secret_key": "SECRET1"},
{"access_key": "KEY2", "secret_key": "SECRET2"}
]
OptionTypeDefaultDescription
levelstringinfoMinimum log level

Log levels: debug, info, warn, error

All configuration options can be set via environment variables using the STOWRY_ prefix with underscores replacing dots.

Config PathEnvironment Variable
server.portSTOWRY_SERVER_PORT
server.modeSTOWRY_SERVER_MODE
server.max_upload_sizeSTOWRY_SERVER_MAX_UPLOAD_SIZE
service.cleanup_timeoutSTOWRY_SERVICE_CLEANUP_TIMEOUT
database.typeSTOWRY_DATABASE_TYPE
database.dsnSTOWRY_DATABASE_DSN
database.tables.meta_dataSTOWRY_DATABASE_TABLES_META_DATA
storage.pathSTOWRY_STORAGE_PATH
auth.readSTOWRY_AUTH_READ
auth.writeSTOWRY_AUTH_WRITE
auth.aws.regionSTOWRY_AUTH_AWS_REGION
auth.aws.serviceSTOWRY_AUTH_AWS_SERVICE
log.levelSTOWRY_LOG_LEVEL

Example:

Terminal window
STOWRY_SERVER_PORT=8080 \
STOWRY_DATABASE_TYPE=postgres \
STOWRY_DATABASE_DSN="postgres://localhost/stowry" \
./stowry serve

Global flags available for all commands:

Terminal window
--config, -c string Config file paths (can be specified multiple times, merged left-to-right)
--db-type string Database type (sqlite, postgres)
--db-dsn string Database connection string
--storage-path string Storage directory path

Example:

Terminal window
./stowry serve --config /etc/stowry/config.yaml --db-type postgres
server:
port: 5708
mode: store
database:
type: sqlite
dsn: dev.db
tables:
meta_data: stowry_metadata
storage:
path: ./uploads
auth:
read: public
write: public
log:
level: debug
server:
port: 5708
mode: store
max_upload_size: 104857600 # 100MB upload limit
service:
cleanup_timeout: 30
database:
type: postgres
dsn: postgres://stowry:${DB_PASSWORD}@db.example.com:5432/stowry?sslmode=require
tables:
meta_data: stowry_metadata
storage:
path: /var/lib/stowry/data
auth:
read: private
write: private
aws:
region: us-east-1
service: s3
keys:
inline:
- access_key: ${STOWRY_ACCESS_KEY}
secret_key: ${STOWRY_SECRET_KEY}
log:
level: info
server:
port: 80
mode: static
database:
type: sqlite
dsn: metadata.db
tables:
meta_data: stowry_metadata
storage:
path: /var/www/html
auth:
read: public
write: public # Auth settings are ignored in static mode (always public)
server:
port: 3000
mode: spa
database:
type: sqlite
dsn: app.db
tables:
meta_data: stowry_metadata
storage:
path: ./dist
auth:
read: public
write: public # Auth settings are ignored in spa mode (always public)