3 Configuration
Insidious Fiddler edited this page 2026-02-06 21:04:12 +00:00

Configuration

Hoist uses a YAML configuration file (config.yaml) with environment variable overrides.

Configuration Loading

  1. Load defaults
  2. Read config.yaml from /etc/hoist/ or current directory
  3. Apply environment variable overrides (prefixed HOIST_)

Environment variables use the format HOIST_<SECTION>_<KEY>:

  • HOIST_SERVER_PORT=8080
  • HOIST_POSTGRES_HOST=db.example.com
  • HOIST_AUTH_JWT_SECRET=your-secret

Generate Configuration Template

go run ./cmd/gen-config

This creates config.yaml and .env.example with all options documented.

Full Configuration Reference

Server

HTTP server settings.

server:
  host: 0.0.0.0           # Bind address
  port: 4340              # Listen port
  read_timeout: 15s       # HTTP read timeout
  write_timeout: 15s      # HTTP write timeout

Logging

log:
  level: info             # trace, debug, info, warn, error
  format: json            # json, pretty
  no_color: false         # Disable colored output
  file: ""                # Log file path (stdout if empty)

Database (PostgreSQL)

postgres:
  host: localhost
  port: 5432
  database: hoist
  username: hoist
  password: ""            # Set via HOIST_POSTGRES_PASSWORD
  max_conns: 25           # Maximum connections
  min_conns: 5            # Minimum connections
  conn_max_lifetime: 1h   # Max connection lifetime
  conn_max_idle_time: 30m # Max idle time

Redis

redis:
  host: localhost
  port: 6379
  password: ""            # Set via HOIST_REDIS_PASSWORD
  database: 0             # Redis database number

Cache

cache:
  flag_ttl: 60s           # Flag config cache TTL
  api_key_ttl: 5m         # API key validation cache TTL
  prefix: "hoist:"        # Redis key prefix

Authentication

auth:
  jwt_secret: ""          # Set via HOIST_AUTH_JWT_SECRET (min 32 chars, REQUIRED)
  jwt_expiry: 15m         # Access token expiry
  refresh_token_expiry: 168h  # Refresh token expiry (7 days)

  local:
    enabled: true         # Enable email/password auth
    allow_registration: true  # Allow new user registration

  mfa:
    enabled: true         # Enable MFA/TOTP support
    issuer: Hoist         # Issuer name in authenticator apps

OAuth/OIDC Providers

Configure external identity providers:

auth:
  oidc:
    - name: google
      display_name: "Sign in with Google"
      client_id: "your-client-id"
      client_secret: ""   # Set via HOIST_AUTH_OIDC_GOOGLE_CLIENT_SECRET
      discovery_url: "https://accounts.google.com/.well-known/openid-configuration"
      scopes:
        - openid
        - email
        - profile
      icon_url: "https://example.com/google-icon.svg"

    - name: github
      display_name: "Sign in with GitHub"
      client_id: "your-client-id"
      client_secret: ""   # Set via HOIST_AUTH_OIDC_GITHUB_CLIENT_SECRET
      discovery_url: "https://token.actions.githubusercontent.com/.well-known/openid-configuration"
      scopes:
        - openid
        - user:email

SMTP (Email)

smtp:
  host: localhost
  port: 587
  username: ""            # Set via HOIST_SMTP_USERNAME
  password: ""            # Set via HOIST_SMTP_PASSWORD
  from_address: "noreply@hoist.local"
  from_name: Hoist
  tls: true
  base_url: "http://localhost:4340"  # Base URL for email links

Security

security:
  allowed_origins: []     # CORS allowed origins (empty = allow all)
  rate_limit:
    requests_per_minute: 100  # Rate limit per client
    backend: memory       # memory or redis

Real-time (WebSocket)

realtime:
  ping_interval: 30s      # Interval between ping messages
  pong_timeout: 10s       # Timeout for pong response

Background Worker

worker:
  enabled: true           # Enable job processing
  concurrency: 10         # Default concurrent processors
  key_prefix: "hoist:jobs"  # Redis key prefix for queues
  stalled_interval: 30s   # Check interval for stalled jobs
  max_retries: 3          # Default retry attempts
  retry_delay: 1s         # Base delay between retries

  queues:
    email:
      concurrency: 5
      max_retries: 5
    analytics:
      concurrency: 2
      max_retries: 3
    cache:
      concurrency: 10
      max_retries: 2
    cleanup:
      concurrency: 1
      max_retries: 3

File Storage

storage:
  backend: local          # local, s3, or empty to disable
  max_file_size: 5242880  # 5MB
  allowed_mime:
    - image/jpeg
    - image/png
    - image/gif
    - image/webp
    - image/svg+xml
  serve_url: /api/files   # URL path for serving files

  local:
    path: ./uploads       # Local storage directory

  s3:
    bucket: ""
    region: us-east-1
    endpoint: ""          # Custom endpoint for S3-compatible services
    access_key_id: ""     # Set via HOIST_STORAGE_S3_ACCESS_KEY_ID
    secret_access_key: "" # Set via HOIST_STORAGE_S3_SECRET_ACCESS_KEY
    use_path_style: false # Use path-style URLs
    cdn: ""               # CDN URL for serving files
    serve_via_api: false  # Serve through API instead of direct S3 URLs

OpenTelemetry

telemetry:
  enabled: false
  service_name: hoist

  traces:
    enabled: true
    endpoint: "localhost:4318"
    protocol: http        # http or grpc
    insecure: true
    sample_rate: 1.0      # 0.0 to 1.0

  metrics:
    enabled: true
    endpoint: "localhost:4318"
    protocol: http
    insecure: true
    interval: 60s

Frontend

frontend:
  dev_mode: false         # Proxy to Vite dev server
  dev_url: ""             # Default: http://localhost:5173

Environment Variables Summary

Variable Description Required
HOIST_AUTH_JWT_SECRET JWT signing secret (min 32 chars) Yes
HOIST_POSTGRES_PASSWORD PostgreSQL password Yes
HOIST_REDIS_PASSWORD Redis password No
HOIST_SMTP_USERNAME SMTP username No
HOIST_SMTP_PASSWORD SMTP password No
HOIST_AUTH_OIDC_<NAME>_CLIENT_SECRET OIDC provider secret Per provider
HOIST_STORAGE_S3_ACCESS_KEY_ID S3 access key If using S3
HOIST_STORAGE_S3_SECRET_ACCESS_KEY S3 secret key If using S3

Example Production Config

server:
  host: 0.0.0.0
  port: 4340

log:
  level: info
  format: json

postgres:
  host: db.internal
  port: 5432
  database: hoist
  username: hoist
  max_conns: 50

redis:
  host: redis.internal
  port: 6379

auth:
  jwt_expiry: 15m
  refresh_token_expiry: 168h
  local:
    enabled: true
    allow_registration: false
  mfa:
    enabled: true

security:
  allowed_origins:
    - https://flags.example.com
  rate_limit:
    requests_per_minute: 200
    backend: redis

telemetry:
  enabled: true
  service_name: hoist-production
  traces:
    endpoint: "otel-collector:4318"
  metrics:
    endpoint: "otel-collector:4318"

Next Steps