Configuration Reference: Server, Database, Storage
Configuration
Section titled “Configuration”Stowry uses a YAML configuration file with environment variable overrides.
Configuration Precedence
Section titled “Configuration Precedence”Configuration values are loaded in this order (later sources override earlier ones):
- Default values
- Configuration file (
config.yaml) - Environment variables (
STOWRY_prefix) - Command-line flags
Full Configuration Reference
Section titled “Full Configuration Reference”# Server configurationserver: 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 configurationservice: cleanup_timeout: 30s # Cleanup operation timeout (default: 30s)
# Database configurationdatabase: type: sqlite # Database type: sqlite, postgres (default: sqlite) dsn: stowry.db # Connection string, file path, or :memory: (default: :memory:) tables: meta_data: stowry_metadata # Metadata table name (default: stowry_metadata)
# Storage configurationstorage: path: ./data # Directory for file storage, or :memory: (default: :memory:)
# Server the client commands talk toendpoint: http://localhost:5708
# Authentication configurationauth: 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) access_key: AKIAIOSFODNN7EXAMPLE secret_key: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY keys: # file: /path/to/keys.json # Several pairs
# Logginglog: level: info # Log level: debug, info, warn, error (default: info)Configuration Sections
Section titled “Configuration Sections”Server
Section titled “Server”| Option | Type | Default | Description |
|---|---|---|---|
port |
int | 5708 | HTTP server port |
mode |
string | store | Server mode (store, static, spa) |
max_upload_size |
int | 0 | Maximum upload size in bytes (0 = unlimited) |
error_document |
string | "" |
Custom 404 page path for static/SPA modes (empty = built-in HTML) |
Service
Section titled “Service”| Option | Type | Default | Description |
|---|---|---|---|
cleanup_timeout |
duration | 30s | Cleanup operation timeout. A bare number is nanoseconds, so write 30s. |
Database
Section titled “Database”| Option | Type | Default | Description |
|---|---|---|---|
type |
string | sqlite | Database type (sqlite requires 3.24+, postgres) |
dsn |
string | :memory: |
Connection string, file path, or :memory: |
migrate |
bool | false | Create the schema before the command does its own work |
tables.meta_data |
string | stowry_metadata | Metadata table name (lowercase, alphanumeric with underscores, max 63 chars) |
Migration Options:
- CLI migration (recommended): Run
stowry migratebefore starting the server - Manual SQL: Execute the schema SQL below directly in your database
PostgreSQL Schema
Section titled “PostgreSQL Schema”-- Table name must be lowercase, alphanumeric with underscores, max 63 charsCREATE 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_atON stowry_metadata (deleted_at)WHERE (deleted_at IS NOT NULL);
CREATE INDEX IF NOT EXISTS idx_stowry_metadata_pending_cleanupON 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_listON stowry_metadata (created_at, path)WHERE (deleted_at IS NULL);SQLite Schema
Section titled “SQLite Schema”-- Table name must be lowercase, alphanumeric with underscores, max 63 charsCREATE 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_atON stowry_metadata (deleted_at);
CREATE INDEX IF NOT EXISTS idx_stowry_metadata_pending_cleanupON stowry_metadata (deleted_at, cleaned_up_at);
CREATE INDEX IF NOT EXISTS idx_stowry_metadata_active_listON stowry_metadata (created_at, path);SQLite DSN Examples:
dsn: stowry.db # File-based databasedsn: :memory: # In-memory (testing only)dsn: /var/lib/stowry/db # Absolute pathPostgreSQL DSN Examples:
dsn: postgres://user:password@localhost:5432/stowrydsn: postgres://user:password@localhost:5432/stowry?sslmode=disabledsn: host=localhost port=5432 user=stowry password=secret dbname=stowryStorage
Section titled “Storage”| Option | Type | Default | Description |
|---|---|---|---|
path |
string | :memory: |
Directory for file storage, or :memory: |
populate |
bool | false | Record the files already under path before the server starts |
The storage directory is created automatically with 0o700 permissions
(owner-only). Files are organized by their path, keeping the original directory
structure. A deployment where another container needs read access should
pre-create the directory with 0o750.
| Option | Type | Default | Description |
|---|---|---|---|
read |
string | public | Read access mode (public, private) |
write |
string | public | Write access mode (public, private) |
aws.region |
string | us-east-1 | AWS region for signature verification |
aws.service |
string | s3 | AWS service name |
access_key |
string | - | Access key for signed requests |
secret_key |
string | - | Secret for that access key |
keys.file |
string | - | Path to a JSON file of key pairs, for more than one |
Note: The access control matrix below applies to
storemode only. Instaticandspamodes, all access is public and write operations return405 Method Not Allowed.
Access Control Matrix:
| read | write | GET | PUT | DELETE |
|---|---|---|---|---|
| public | public | Public | Public | Public |
| public | private | Public | Auth required | Auth required |
| private | private | Auth required | Auth required | Auth required |
| private | public | Auth required | Public | Public |
The config carries one key pair. Either half alone is rejected at startup.
auth: read: private write: private access_key: KEY1 secret_key: SECRET1Several keys, from a file:
auth: keys: file: /path/to/keys.jsonWhere keys.json contains:
[ {"access_key": "KEY1", "secret_key": "SECRET1"}, {"access_key": "KEY2", "secret_key": "SECRET2"}]| Option | Type | Default | Description |
|---|---|---|---|
level |
string | info | Minimum log level |
Log levels: debug, info, warn, error
Environment Variables
Section titled “Environment Variables”All configuration options can be set via environment variables using the STOWRY_ prefix with underscores replacing dots.
| Config Path | Environment Variable |
|---|---|
server.port |
STOWRY_SERVER_PORT |
server.mode |
STOWRY_SERVER_MODE |
server.max_upload_size |
STOWRY_SERVER_MAX_UPLOAD_SIZE |
service.cleanup_timeout |
STOWRY_SERVICE_CLEANUP_TIMEOUT |
database.migrate |
STOWRY_DATABASE_MIGRATE |
storage.populate |
STOWRY_STORAGE_POPULATE |
cors.allowed_origins |
STOWRY_CORS_ALLOWED_ORIGINS |
cors.allowed_methods |
STOWRY_CORS_ALLOWED_METHODS |
cors.allowed_headers |
STOWRY_CORS_ALLOWED_HEADERS |
cors.exposed_headers |
STOWRY_CORS_EXPOSED_HEADERS |
cors.allow_credentials |
STOWRY_CORS_ALLOW_CREDENTIALS |
cors.max_age |
STOWRY_CORS_MAX_AGE |
database.type |
STOWRY_DATABASE_TYPE |
database.dsn |
STOWRY_DATABASE_DSN |
database.tables.meta_data |
STOWRY_DATABASE_TABLES_META_DATA |
storage.path |
STOWRY_STORAGE_PATH |
auth.read |
STOWRY_AUTH_READ |
auth.write |
STOWRY_AUTH_WRITE |
auth.aws.region |
STOWRY_AUTH_AWS_REGION |
auth.aws.service |
STOWRY_AUTH_AWS_SERVICE |
auth.keys.file |
STOWRY_AUTH_KEYS_FILE |
auth.access_key |
STOWRY_ACCESS_KEY |
auth.secret_key |
STOWRY_SECRET_KEY |
endpoint |
STOWRY_ENDPOINT |
log.level |
STOWRY_LOG_LEVEL |
The credentials are the exception to the STOWRY_ + path rule, dropping the
section name. Each setting answers to exactly one variable, so
STOWRY_AUTH_ACCESS_KEY is not read.
Example:
STOWRY_SERVER_PORT=8080 \STOWRY_DATABASE_TYPE=postgres \STOWRY_DATABASE_DSN="postgres://localhost/stowry" \./stowry serveCommand-Line Flags
Section titled “Command-Line Flags”Every setting has a flag. stowry --help lists them all with the environment
variable each one mirrors; the ones reached for most often:
-c, --config strings Config file paths, merged left to right --db-type string Database type (sqlite, postgres)-d, --db-dsn string Database connection string-s, --storage-path string Storage directory path-a, --access-key string Access key for signed requests-k, --secret-key string Secret key for signed requests-e, --endpoint string Server the client commands talk to --log-level string debug, info, warn or errorserve adds --port, --mode, -m/--migrate and -p/--populate.
Example:
./stowry serve --config /etc/stowry/config.yaml --db-type postgresConfiguration Examples
Section titled “Configuration Examples”Development (SQLite)
Section titled “Development (SQLite)”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: debugProduction (PostgreSQL)
Section titled “Production (PostgreSQL)”server: port: 5708 mode: store max_upload_size: 104857600 # 100MB upload limit
service: cleanup_timeout: 30s
database: type: postgres # No shell expansion here; set STOWRY_DATABASE_DSN to keep the password out of the file dsn: postgres://stowry:CHANGEME@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 # Credentials come from STOWRY_ACCESS_KEY and STOWRY_SECRET_KEY
log: level: infoStatic File Server
Section titled “Static File Server”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 # ignored in static mode; auth.read: private would fail at startupSPA Hosting
Section titled “SPA Hosting”server: port: 3000 mode: spa
database: type: sqlite dsn: app.db tables: meta_data: stowry_metadata
storage: path: ./dist
auth: read: public write: public # ignored in spa mode; auth.read: private would fail at startup