Configuration Reference
Complete reference for Horizon Epoch configuration options.
Configuration Sources
Configuration is loaded from (in order of precedence):
- Command-line arguments (highest priority)
- Environment variables
- Local repository configuration (
.epoch/config) - Configuration file (
epoch.toml) - Default values (lowest priority)
Configuration File Search Order
The CLI searches for configuration files in this order:
./epoch.toml(current directory)./config/epoch.toml./.epoch/config.toml~/.config/epoch/config.toml/etc/epoch/config.toml
The first file found is used. Override with --config or EPOCH_CONFIG_FILE.
Configuration File
Default location: ~/.epoch/config.toml or ./epoch.toml
Full Example
# epoch.toml
[metadata]
url = "postgresql://localhost/horizon_epoch"
pool_size = 10
connect_timeout = 30
[defaults]
branch = "main"
author_name = "Your Name"
author_email = "you@example.com"
format = "text"
[logging]
level = "info"
format = "pretty" # or "json"
file = "/var/log/epoch/epoch.log"
# PostgreSQL storage backends
[storage.postgres.production]
url = "postgresql://user:pass@prod-db.example.com/production"
pool_size = 20
connect_timeout = 30
[storage.postgres.staging]
host = "staging-db.example.com"
port = 5432
database = "staging"
username = "epoch_user"
password_file = "/run/secrets/db-password"
sslmode = "verify-full"
ssl_rootcert = "/etc/ssl/certs/ca.crt"
[storage.postgres.secure]
host = "secure-db.internal"
database = "secure"
vault_path = "secret/data/secure-db"
[storage.postgres.secure.ssh_tunnel]
host = "bastion.example.com"
user = "ubuntu"
key_file = "~/.ssh/id_rsa"
# S3 storage backends
[storage.s3.datalake]
bucket = "company-datalake"
region = "us-east-1"
prefix = "horizon-epoch/"
[storage.s3.partner]
bucket = "partner-shared"
region = "us-west-2"
assume_role_arn = "arn:aws:iam::123456789012:role/PartnerAccess"
external_id = "partner-123"
[storage.s3.minio]
bucket = "local-data"
endpoint = "http://localhost:9000"
access_key = "minioadmin"
secret_key = "minioadmin"
force_path_style = true
# Vault integration
[vault]
addr = "https://vault.example.com:8200"
auth_method = "approle"
role_id = "xxx-xxx-xxx"
secret_id_file = "/run/secrets/vault-secret-id"
ca_cert = "/etc/ssl/certs/vault-ca.crt"
# AWS integration
[aws]
region = "us-east-1"
profile = "production"
# Credential caching
[credentials]
cache_enabled = true
cache_ttl = 300
refresh_before_expiry = 60
Environment Variables
All configuration can be set via environment variables with EPOCH_ prefix:
Core Settings
| Variable | Description | Default |
|---|---|---|
EPOCH_METADATA_URL | Metadata database URL | - |
DATABASE_URL | Fallback for metadata URL (SQLx compatible) | - |
EPOCH_CONFIG_FILE | Config file path | ~/.epoch/config.toml |
EPOCH_DEFAULT_BRANCH | Default branch name | main |
EPOCH_FORMAT | Output format | text |
Author Settings
| Variable | Description | Default |
|---|---|---|
EPOCH_AUTHOR_NAME | Default author name for commits | git config user.name |
EPOCH_AUTHOR_EMAIL | Default author email for commits | git config user.email |
Author information is resolved in this priority order:
- Command-line arguments (
--author-name,--author-email) - Environment variables (
EPOCH_AUTHOR_NAME,EPOCH_AUTHOR_EMAIL) - Local repository config (
.epoch/config) - Git configuration (
git config user.name,git config user.email)
Editor Settings
| Variable | Description | Default |
|---|---|---|
EPOCH_EDITOR | Editor for interactive operations | - |
EDITOR | Fallback editor | - |
VISUAL | Secondary fallback editor | - |
Editor is selected in priority order: EPOCH_EDITOR > EDITOR > VISUAL > platform default (vi on Unix, notepad.exe on Windows).
Commit Signing
| Variable | Description | Default |
|---|---|---|
EPOCH_SIGNING_KEY | Path to signing key file (ASCII-armored) | - |
EPOCH_SIGNING_KEY_PASSWORD | Password for signing key | - (prompts) |
Logging
| Variable | Description | Default |
|---|---|---|
EPOCH_LOG_LEVEL | Log level (error/warn/info/debug/trace) | info |
EPOCH_LOG_FORMAT | Log format (pretty/json) | pretty |
EPOCH_LOG_FILE | Log file path | - |
RUST_LOG | Rust logging filter (module=level format) | - |
API Server
| Variable | Description | Default |
|---|---|---|
EPOCH_API_HOST | API server bind address | 0.0.0.0 |
EPOCH_API_PORT | API server port | 8000 |
EPOCH_API_PREFIX | API route prefix | /api/v1 |
EPOCH_DEBUG | Enable debug mode (exposes Swagger UI) | false |
EPOCH_SERVER_URL | Remote server URL for CLI | - |
OAuth/OIDC Authentication
| Variable | Description |
|---|---|
EPOCH_OAUTH_CLIENT_ID | Default OAuth client ID |
EPOCH_OAUTH_CLIENT_SECRET | Default OAuth client secret |
EPOCH_OAUTH_{PROVIDER}_CLIENT_ID | Provider-specific client ID |
EPOCH_OAUTH_{PROVIDER}_CLIENT_SECRET | Provider-specific client secret |
EPOCH_OAUTH_OIDC_ISSUER | OIDC issuer URL for custom provider |
Supported providers: GITHUB, GOOGLE, AZURE, OKTA, OIDC (custom).
Example:
# GitHub OAuth
export EPOCH_OAUTH_GITHUB_CLIENT_ID="your-client-id"
export EPOCH_OAUTH_GITHUB_CLIENT_SECRET="your-client-secret"
epoch auth login --method oauth --provider github
# Custom OIDC provider
export EPOCH_OAUTH_CLIENT_ID="your-client-id"
export EPOCH_OAUTH_OIDC_ISSUER="https://your-idp.example.com"
epoch auth login --method oauth --provider oidc
PostgreSQL
| Variable | Description |
|---|---|
EPOCH_POSTGRES_{NAME}_URL | Full connection URL |
EPOCH_POSTGRES_{NAME}_HOST | Database host |
EPOCH_POSTGRES_{NAME}_PORT | Database port |
EPOCH_POSTGRES_{NAME}_DATABASE | Database name |
EPOCH_POSTGRES_{NAME}_USERNAME | Username |
EPOCH_POSTGRES_{NAME}_PASSWORD | Password |
EPOCH_POSTGRES_{NAME}_SSLMODE | SSL mode |
S3
| Variable | Description |
|---|---|
EPOCH_S3_{NAME}_BUCKET | Bucket name |
EPOCH_S3_{NAME}_REGION | AWS region |
EPOCH_S3_{NAME}_ENDPOINT | Custom endpoint |
EPOCH_S3_{NAME}_ACCESS_KEY | Access key ID |
EPOCH_S3_{NAME}_SECRET_KEY | Secret access key |
AWS_ACCESS_KEY_ID | Default AWS access key |
AWS_SECRET_ACCESS_KEY | Default AWS secret key |
AWS_DEFAULT_REGION | Default AWS region |
MySQL
| Variable | Description |
|---|---|
EPOCH_MYSQL_{NAME}_URL | Full connection URL |
EPOCH_MYSQL_{NAME}_HOST | Database host |
EPOCH_MYSQL_{NAME}_PORT | Database port |
EPOCH_MYSQL_{NAME}_DATABASE | Database name |
EPOCH_MYSQL_{NAME}_USERNAME | Username |
EPOCH_MYSQL_{NAME}_PASSWORD | Password |
SQL Server
| Variable | Description |
|---|---|
EPOCH_MSSQL_{NAME}_URL | Full connection URL |
EPOCH_MSSQL_{NAME}_HOST | Database host |
EPOCH_MSSQL_{NAME}_PORT | Database port |
EPOCH_MSSQL_{NAME}_DATABASE | Database name |
EPOCH_MSSQL_{NAME}_USERNAME | Username |
EPOCH_MSSQL_{NAME}_PASSWORD | Password |
SQLite
| Variable | Description |
|---|---|
EPOCH_SQLITE_{NAME}_PATH | Database file path |
Azure Blob Storage
| Variable | Description |
|---|---|
EPOCH_AZURE_{NAME}_ACCOUNT | Storage account name |
EPOCH_AZURE_{NAME}_CONTAINER | Container name |
EPOCH_AZURE_{NAME}_CONNECTION_STRING | Connection string |
EPOCH_AZURE_{NAME}_ACCESS_KEY | Storage access key |
AZURE_TENANT_ID | Azure AD tenant ID |
AZURE_CLIENT_ID | Azure AD client ID |
AZURE_CLIENT_SECRET | Azure AD client secret |
Google Cloud Storage
| Variable | Description |
|---|---|
EPOCH_GCS_{NAME}_BUCKET | Bucket name |
EPOCH_GCS_{NAME}_PROJECT | GCP project ID |
GOOGLE_APPLICATION_CREDENTIALS | Service account key file path |
Local Filesystem
| Variable | Description |
|---|---|
EPOCH_LOCAL_{NAME}_PATH | Base directory path |
Vault
| Variable | Description |
|---|---|
VAULT_ADDR | Vault server address |
VAULT_TOKEN | Vault token |
VAULT_ROLE_ID | AppRole role ID |
VAULT_SECRET_ID | AppRole secret ID |
SSH
| Variable | Description |
|---|---|
EPOCH_SSH_HOST | SSH tunnel host |
EPOCH_SSH_USER | SSH username |
EPOCH_SSH_KEY_FILE | SSH private key path |
SSH_AUTH_SOCK | SSH agent socket |
Configuration Sections
[metadata]
Metadata database configuration.
| Option | Type | Default | Description |
|---|---|---|---|
url | string | - | PostgreSQL connection URL |
pool_size | int | 10 | Connection pool size |
connect_timeout | int | 30 | Connection timeout (seconds) |
idle_timeout | int | 600 | Idle connection timeout |
max_lifetime | int | 3600 | Max connection lifetime |
[defaults]
Default values for operations.
| Option | Type | Default | Description |
|---|---|---|---|
branch | string | “main” | Default branch |
author_name | string | - | Default author name |
author_email | string | - | Default author email |
format | string | “text” | Output format |
[logging]
Logging configuration.
| Option | Type | Default | Description |
|---|---|---|---|
level | string | “info” | Log level |
format | string | “pretty” | Log format |
file | string | - | Log file path |
json | bool | false | JSON log format |
[storage.postgres.{name}]
PostgreSQL backend configuration.
| Option | Type | Default | Description |
|---|---|---|---|
url | string | - | Full connection URL |
host | string | - | Database host |
port | int | 5432 | Database port |
database | string | - | Database name |
username | string | - | Username |
password | string | - | Password |
password_file | string | - | Password file path |
sslmode | string | “prefer” | SSL mode |
ssl_cert | string | - | Client certificate |
ssl_key | string | - | Client key |
ssl_rootcert | string | - | CA certificate |
pool_size | int | 10 | Pool size |
connect_timeout | int | 30 | Timeout |
vault_path | string | - | Vault secret path |
vault_role | string | - | Vault dynamic role |
aws_secret_id | string | - | AWS Secrets Manager ID |
use_iam_auth | bool | false | Use RDS IAM auth |
[storage.postgres.{name}.ssh_tunnel]
SSH tunnel configuration for PostgreSQL.
| Option | Type | Default | Description |
|---|---|---|---|
host | string | - | Bastion host |
port | int | 22 | SSH port |
user | string | - | SSH username |
key_file | string | - | Private key path |
key_passphrase | string | - | Key passphrase |
use_agent | bool | false | Use SSH agent |
known_hosts_file | string | - | Known hosts file |
strict_host_key_checking | bool/string | true | Host key checking |
keepalive_interval | int | 60 | Keepalive interval |
connect_timeout | int | 30 | Connection timeout |
auto_reconnect | bool | true | Auto-reconnect |
[storage.s3.{name}]
S3 backend configuration.
| Option | Type | Default | Description |
|---|---|---|---|
bucket | string | - | Bucket name |
region | string | - | AWS region |
endpoint | string | - | Custom endpoint |
prefix | string | “” | Key prefix |
access_key | string | - | Access key ID |
secret_key | string | - | Secret access key |
session_token | string | - | Session token |
force_path_style | bool | false | Path-style URLs |
use_instance_credentials | bool | false | Use instance profile |
assume_role_arn | string | - | Role to assume |
external_id | string | - | External ID |
vault_path | string | - | Vault secret path |
aws_secret_id | string | - | Secrets Manager ID |
[storage.mysql.{name}]
MySQL backend configuration.
| Option | Type | Default | Description |
|---|---|---|---|
url | string | - | Full connection URL |
host | string | - | Database host |
port | int | 3306 | Database port |
database | string | - | Database name |
username | string | - | Username |
password | string | - | Password |
password_file | string | - | Password file path |
ssl_mode | string | “preferred” | SSL mode |
ssl_ca | string | - | CA certificate |
pool_size | int | 10 | Pool size |
connect_timeout | int | 30 | Timeout |
vault_path | string | - | Vault secret path |
[storage.mysql.{name}.ssh_tunnel]
SSH tunnel configuration for MySQL (same options as PostgreSQL).
[storage.mssql.{name}]
SQL Server backend configuration.
| Option | Type | Default | Description |
|---|---|---|---|
url | string | - | Full connection URL |
host | string | - | Database host |
port | int | 1433 | Database port |
database | string | - | Database name |
username | string | - | Username |
password | string | - | Password |
password_file | string | - | Password file path |
trust_cert | bool | false | Trust server certificate |
encrypt | bool | true | Encrypt connection |
pool_size | int | 10 | Pool size |
connect_timeout | int | 30 | Timeout |
vault_path | string | - | Vault secret path |
use_windows_auth | bool | false | Use Windows auth |
[storage.sqlite.{name}]
SQLite backend configuration.
| Option | Type | Default | Description |
|---|---|---|---|
path | string | - | Database file path |
mode | string | “rwc” | Open mode (r/rw/rwc) |
in_memory | bool | false | Use in-memory database |
busy_timeout | int | 5000 | Busy timeout (ms) |
journal_mode | string | “wal” | Journal mode |
[storage.azure.{name}]
Azure Blob Storage backend configuration.
| Option | Type | Default | Description |
|---|---|---|---|
account | string | - | Storage account name |
container | string | - | Container name |
prefix | string | “” | Blob prefix |
auth_method | string | “connection_string” | Auth method |
connection_string | string | - | Connection string |
access_key | string | - | Storage access key |
sas_token | string | - | SAS token |
tenant_id | string | - | Azure AD tenant ID |
client_id | string | - | Azure AD client ID |
client_secret | string | - | Azure AD client secret |
use_managed_identity | bool | false | Use managed identity |
vault_path | string | - | Vault secret path |
[storage.gcs.{name}]
Google Cloud Storage backend configuration.
| Option | Type | Default | Description |
|---|---|---|---|
bucket | string | - | Bucket name |
project_id | string | - | GCP project ID |
prefix | string | “” | Object prefix |
auth_method | string | “service_account” | Auth method |
credentials_file | string | - | Service account key file |
use_adc | bool | false | Use Application Default Credentials |
vault_path | string | - | Vault secret path |
[storage.local.{name}]
Local filesystem backend configuration.
| Option | Type | Default | Description |
|---|---|---|---|
path | string | - | Base directory path |
create_dirs | bool | true | Create directories if missing |
[vault]
HashiCorp Vault configuration.
| Option | Type | Default | Description |
|---|---|---|---|
addr | string | - | Vault address |
token | string | - | Vault token |
auth_method | string | “token” | Auth method |
role_id | string | - | AppRole role ID |
secret_id | string | - | AppRole secret ID |
secret_id_file | string | - | Secret ID file |
role | string | - | K8s/AWS role |
ca_cert | string | - | CA certificate |
skip_verify | bool | false | Skip TLS verify |
namespace | string | - | Vault namespace |
[aws]
AWS configuration.
| Option | Type | Default | Description |
|---|---|---|---|
region | string | - | Default region |
profile | string | - | AWS profile |
access_key_id | string | - | Access key |
secret_access_key | string | - | Secret key |
[credentials]
Credential caching configuration.
| Option | Type | Default | Description |
|---|---|---|---|
cache_enabled | bool | true | Enable caching |
cache_ttl | int | 300 | Cache TTL (seconds) |
cache_max_size | int | 100 | Max cache entries |
refresh_before_expiry | int | 60 | Refresh threshold |
Variable Substitution
Environment variables can be referenced in config:
[storage.postgres.production]
password = "${DB_PASSWORD}"
File contents can be referenced:
[storage.postgres.production]
password = "@file:/run/secrets/db-password"
Profiles
Multiple profiles can be defined:
[profiles.development]
metadata.url = "postgresql://localhost/horizon_epoch_dev"
[profiles.production]
metadata.url = "postgresql://prod-db/horizon_epoch"
Switch profiles:
epoch --profile production status
Local Repository Configuration
When you initialize a repository with epoch init, a .epoch/ directory is created with local configuration.
Directory Structure
.epoch/
├── config # Repository configuration (TOML)
├── HEAD # Current branch reference
└── refs/
├── heads/ # Branch references
└── tags/ # Tag references
Local Config File (.epoch/config)
# Repository identity
repository_name = "my-data-repo"
repository_id = "550e8400-e29b-41d4-a716-446655440000"
# Metadata database connection
metadata_url = "postgresql://localhost/horizon_epoch"
# Current branch (also tracked in HEAD file)
current_branch = "main"
# Author information (optional, overrides global config)
[author]
name = "Your Name"
email = "you@example.com"
# Branching configuration (optional)
[branching]
strategy = "environment" # or "gitflow", "trunk"
[branching.promotion]
paths = [
{ source = "development", target = "staging" },
{ source = "staging", target = "production" }
]
require_approval = true
HEAD File
The HEAD file tracks the current branch:
ref: refs/heads/main
Or in detached HEAD state (direct commit reference):
abc123def456...
DDL Configuration
DDL (Data Definition Language) execution settings for schema changes.
[ddl]
| Option | Type | Default | Description |
|---|---|---|---|
lock_timeout_secs | int | 30 | Lock acquisition timeout |
statement_timeout_secs | int | 300 | Statement execution timeout |
check_table_stats | bool | true | Check table size before DDL |
use_concurrent | bool | false | Use concurrent index operations |
warn_large_table_rows | int | 1000000 | Warn if table exceeds rows |
warn_large_table_bytes | int | 1073741824 | Warn if table exceeds bytes (1GB) |
[ddl.retry]
| Option | Type | Default | Description |
|---|---|---|---|
max_retries | int | 3 | Maximum retry attempts |
initial_delay_ms | int | 500 | Initial retry delay |
max_delay_ms | int | 30000 | Maximum retry delay |
backoff_multiplier | float | 2.0 | Exponential backoff factor |
Example:
[ddl]
lock_timeout_secs = 30
statement_timeout_secs = 300
check_table_stats = true
[ddl.retry]
max_retries = 3
initial_delay_ms = 500
max_delay_ms = 30000
Branching Configuration
[branching]
| Option | Type | Default | Description |
|---|---|---|---|
strategy | string | “environment” | Branching strategy |
default_branch | string | “main” | Default branch name |
protected_branches | array | [“main”, “production”] | Protected branch patterns |
Branching Strategies
environment (default):
- Branches represent environments (development, staging, production)
- Promotion flows upward through environments
- Good for data pipelines and ETL workflows
gitflow:
- Feature branches, develop, release, hotfix, main
- Traditional Git Flow pattern adapted for data
- Good for teams familiar with Git Flow
trunk:
- Single main branch with short-lived feature branches
- Continuous integration style
- Good for fast-moving projects
[branching.promotion]
| Option | Type | Default | Description |
|---|---|---|---|
paths | array | [] | Allowed promotion paths |
require_approval | bool | false | Require approval for promotions |
auto_merge | bool | true | Auto-merge if no conflicts |
conflict_strategy | string | “fail” | Conflict handling (fail/ours/theirs) |
Example:
[branching]
strategy = "environment"
default_branch = "development"
protected_branches = ["staging", "production"]
[branching.promotion]
paths = [
{ source = "development", target = "staging" },
{ source = "staging", target = "production" }
]
require_approval = true
conflict_strategy = "fail"
Conflict Handling
[conflict]
| Option | Type | Default | Description |
|---|---|---|---|
default_strategy | string | “manual” | Default conflict resolution |
auto_resolve_schema | bool | false | Auto-resolve schema conflicts |
[conflict.table_rules]
Per-table conflict rules:
[conflict.table_rules.users]
strategy = "last_write_wins"
timestamp_field = "updated_at"
[conflict.table_rules.audit_log]
strategy = "append_only"
[conflict.field_rules]
Per-field conflict rules:
[conflict.field_rules."users.email"]
strategy = "source_wins"
[conflict.field_rules."users.login_count"]
strategy = "sum"
Strategies: manual, source_wins, target_wins, last_write_wins, sum, max, min, append_only.
Testing and Development
Development Environment Variables
| Variable | Description |
|---|---|
DATABASE_URL | Database URL for tests/development |
TEST_DATABASE_URL | Alternative test database URL |
SQLX_OFFLINE | Enable SQLx offline mode (true) |
S3/MinIO Testing
| Variable | Description |
|---|---|
S3_ENDPOINT | S3/MinIO endpoint URL |
S3_BUCKET | Test bucket name |
S3_ACCESS_KEY | Access key for testing |
S3_SECRET_KEY | Secret key for testing |
E2E Testing
| Variable | Description | Default |
|---|---|---|
EPOCH_BIN | Path to CLI binary for tests | ./target/debug/epoch |
E2E_KEEP_TEMP | Keep temporary test directories | false |
E2E_VERBOSE | Verbose test output | false |
Example Development Setup
# .env file for development
DATABASE_URL=postgresql://horizon:horizon_dev_password@localhost:5432/horizon_epoch
EPOCH_METADATA_URL=postgresql://horizon:horizon_dev_password@localhost:5432/horizon_epoch
# MinIO for local S3 testing
EPOCH_S3_ENDPOINT=http://localhost:9000
EPOCH_S3_ACCESS_KEY=minioadmin
EPOCH_S3_SECRET_KEY=minioadmin
EPOCH_S3_BUCKET=horizon-epoch-data
# Development settings
EPOCH_DEBUG=true
EPOCH_LOG_LEVEL=debug
RUST_LOG=horizon_epoch=debug,sqlx=warn
# Author info
EPOCH_AUTHOR_NAME="Development User"
EPOCH_AUTHOR_EMAIL="dev@example.com"
Complete Configuration Example
# epoch.toml - Complete configuration example
# =============================================================================
# Metadata Database
# =============================================================================
[metadata_db]
url = "postgresql://localhost:5432/horizon_epoch"
max_connections = 10
min_connections = 2
# =============================================================================
# Logging
# =============================================================================
[logging]
level = "info"
format = "json" # "pretty" or "json"
# =============================================================================
# DDL Execution
# =============================================================================
[ddl]
lock_timeout_secs = 30
statement_timeout_secs = 300
check_table_stats = true
use_concurrent = false
[ddl.retry]
max_retries = 3
initial_delay_ms = 500
max_delay_ms = 30000
# =============================================================================
# Branching Strategy
# =============================================================================
[branching]
strategy = "environment"
default_branch = "development"
protected_branches = ["staging", "production"]
[branching.promotion]
paths = [
{ source = "development", target = "staging" },
{ source = "staging", target = "production" }
]
require_approval = true
# =============================================================================
# Storage Backends
# =============================================================================
# PostgreSQL backends
[[storage.postgresql]]
name = "primary"
url = "postgresql://localhost:5432/data"
[[storage.postgresql]]
name = "analytics"
host = "analytics-db.internal"
port = 5432
database = "analytics"
[storage.postgresql.credentials]
type = "vault"
addr = "https://vault.example.com:8200"
secret_path = "database/creds/analytics"
[storage.postgresql.tls]
mode = "verify_full"
ca_cert = "/etc/ssl/certs/ca.pem"
# S3 backends
[[storage.s3]]
name = "datalake"
endpoint = "https://s3.amazonaws.com"
bucket = "company-datalake"
region = "us-east-1"
prefix = "epoch/"
[[storage.s3]]
name = "archive"
endpoint = "http://minio.internal:9000"
bucket = "archive"
access_key_id = "${MINIO_ACCESS_KEY}"
secret_access_key = "${MINIO_SECRET_KEY}"
force_path_style = true