Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Configuration

Mycelium reads a single TOML file at startup. Tell it where the file is:

SETTINGS_PATH=settings/config.toml myc-api

Three ways to set a value

Every setting can be defined directly in TOML, via an environment variable, or via Vault:

# Directly in the file (fine for development)
tokenSecret = "my-secret"

# From an environment variable
tokenSecret = { env = "MYC_TOKEN_SECRET" }

# From HashiCorp Vault (recommended for production)
tokenSecret = { vault = { path = "myc/core/accountLifeCycle", key = "tokenSecret" } }

Vault values are resolved at runtime — you don’t need to restart after changing a secret in Vault.


What do I actually need to configure?

For a minimal working instance you need:

  1. [diesel].databaseUrl — PostgreSQL connection string.
  2. [redis] — Redis host and optional password.
  3. [auth].jwtSecret — Random string for signing JWT tokens.
  4. [core.accountLifeCycle].tokenSecret — Random string for email verification tokens.
  5. [smtp] — Email server (for magic-link login emails).
  6. [api].allowedOrigins — Allowed CORS origins for your frontend.

Everything else has sensible defaults. See the Quick Start for a copy-pasteable minimal config.


Section reference

[vault.define] — Secret management

Optional. Required only if you use Vault-sourced values anywhere.

[vault.define]
url = "http://localhost:8200"
versionWithNamespace = "v1/kv"
token = { env = "MYC_VAULT_TOKEN" }
FieldDescription
urlVault server URL including port
versionWithNamespaceAPI version and KV path prefix (e.g. v1/kv)
tokenVault auth token. Use env var or Vault for this value in production

[core.accountLifeCycle] — Identity and email settings

[core.accountLifeCycle]
domainName = "Mycelium"
domainUrl = "https://mycelium.example.com"
tokenExpiration = 3600
noreplyName = "Mycelium No-Reply"
noreplyEmail = "noreply@example.com"
supportName = "Support"
supportEmail = "support@example.com"
locale = "en-US"
tokenSecret = "random-secret"
FieldDescription
domainNameHuman-friendly name shown in emails
domainUrlYour frontend URL — used in email links
tokenExpirationEmail verification token lifetime in seconds
noreplyEmailFrom-address for system emails
supportEmailReply-to address for support
localeEmail language (e.g. en-US, pt-BR)
tokenSecretSecret for signing email verification tokens

[core.webhook] — Webhook dispatch

[core.webhook]
acceptInvalidCertificates = true
consumeIntervalInSecs = 10
consumeBatchSize = 10
maxAttempts = 3
FieldDescription
acceptInvalidCertificatesAllow self-signed TLS certs on webhook targets (use true in dev only)
consumeIntervalInSecsHow often to flush the webhook queue
consumeBatchSizeEvents per flush
maxAttemptsRetry limit per event

[diesel] — Database

[diesel]
databaseUrl = "postgres://mycelium-user:password@localhost:5432/mycelium-dev"

Use Vault for the URL in production:

databaseUrl = { vault = { path = "myc/database", key = "url" } }

[smtp] and [queue] — Email

[smtp]
host = "smtp.gmail.com:587"
username = "user@gmail.com"
password = "your-password"

[queue]
emailQueueName = "email-queue"
consumeIntervalInSecs = 5

[redis] — Cache

[redis]
protocol = "redis"       # "rediss" for TLS
hostname = "localhost:6379"
password = ""

[auth] — Authentication

[auth]
internal = "enabled"
jwtSecret = "random-secret"
jwtExpiresIn = 86400     # 24 hours
tmpExpiresIn = 3600      # temporary tokens (password reset, account creation)

External OAuth2 providers

Add one block per provider:

# Google
[[auth.external.define]]
issuer = "https://accounts.google.com"
jwksUri = "https://www.googleapis.com/oauth2/v3/certs"
userInfoUrl = "https://www.googleapis.com/oauth2/v3/userinfo"
audience = "your-google-client-id"

# Auth0
[[auth.external.define]]
issuer = "https://your-app.auth0.com/"
jwksUri = "https://your-app.auth0.com/.well-known/jwks.json"
userInfoUrl = "https://your-app.auth0.com/userinfo"
audience = "https://your-app.auth0.com/api/v2/"
FieldDescription
issuerProvider’s identity URL
jwksUriURL of the provider’s public keys (for JWT verification)
userInfoUrlURL to fetch the user’s email and claims
audienceClient ID or API identifier registered with the provider

[api] — Server and routing

[api]
serviceIp = "0.0.0.0"
servicePort = 8080
serviceWorkers = 4
gatewayTimeout = 30
healthCheckInterval = 120
maxRetryCount = 3
allowedOrigins = ["http://localhost:3000", "https://app.example.com"]

[api.cache]
jwksTtl = 3600     # cache OAuth2 public keys for 1 hour
emailTtl = 120     # cache resolved emails for 2 minutes
profileTtl = 120   # cache resolved profiles for 2 minutes
FieldDescription
serviceIpBind address. 0.0.0.0 listens on all interfaces
servicePortHTTP port
serviceWorkersWorker threads. Match to CPU count
gatewayTimeoutRequest timeout in seconds
allowedOriginsCORS whitelist. Use ["*"] in dev only
healthCheckIntervalHow often to probe downstream health endpoints (seconds)

[api.logging] — Log output

[api.logging]
level = "info"
format = "ansi"    # "jsonl" for structured logs
target = "stdout"

File target:

target = { file = { path = "logs/api.log" } }

OpenTelemetry collector:

target = { collector = { name = "mycelium-api", host = "otel-collector", protocol = "grpc", port = 4317 } }

[api.tls.define] — TLS (optional)

[api.tls.define]
tlsCert = { vault = { path = "myc/api/tls", key = "tlsCert" } }
tlsKey = { vault = { path = "myc/api/tls", key = "tlsKey" } }

To disable TLS:

tls = "disabled"

[api.services] — Downstream services

Route configuration lives here. See Downstream APIs for the full guide.


Next steps