Skip to content

Declarative Provisioning

Logchef supports declarative provisioning — define your teams, data sources, and access control in a TOML config file instead of (or alongside) the web UI. This enables GitOps workflows where infrastructure config is version-controlled and deployed automatically.

Provisioning uses a managed vs unmanaged strategy:

  • Managed resources — Declared in your provisioning config. Logchef creates, updates, and optionally deletes them on startup. The API rejects manual edits to managed resources.
  • Unmanaged resources — Created via the UI. Provisioning ignores them entirely.

This means you can gradually adopt provisioning: start by declaring a few sources, and leave everything else UI-managed.

manage_sources = true
manage_teams = true
prune = false
dry_run = true # Start with dry-run to verify
[[sources]]
name = "Production Logs"
host = "clickhouse.internal:9000"
username = "logchef"
password = "secret"
database = "logs"
table_name = "otel_logs"
meta_ts_field = "timestamp"
description = "Production application logs"
ttl_days = 30
[[teams]]
name = "Platform"
description = "Platform engineering"
sources = ["Production Logs"]
members = [
{ email = "alice@example.com", role = "admin" },
{ email = "bob@example.com", role = "editor" },
{ email = "carol@example.com", role = "member" },
]
[provisioning]
file = "provisioning.toml"

On startup, Logchef reconciles the declared state with the database. With dry_run = true, it logs what it would do without making changes:

INFO provisioning dry-run complete, rolling back transaction

Once satisfied with the dry-run output, set dry_run = false and restart.

FieldTypeDefaultDescription
manage_sourcesboolfalseEnable declarative source management
manage_teamsboolfalseEnable declarative team management
pruneboolfalseDelete managed resources removed from config
dry_runboolfalseLog changes without applying them
FieldRequiredDefaultDescription
nameYesUnique display name (used as identity key)
hostYesClickHouse host:port
usernameYesClickHouse username
passwordYesClickHouse password (or use secret_ref)
secret_refNoEnvironment variable name containing the password
databaseYesClickHouse database
table_nameYesClickHouse table
meta_ts_fieldNotimestampTimestamp column name
meta_severity_fieldNoSeverity/level column name
descriptionNoHuman-readable description
ttl_daysNo0Data retention in days
FieldRequiredDescription
nameYesUnique display name (used as identity key)
descriptionNoHuman-readable description
sourcesNoList of source names this team can access
membersNoList of team members
FieldRequiredDefaultDescription
emailYesUser’s email (must match OIDC identity)
roleNomemberTeam role: admin, editor, or member

Never commit passwords to version control. Use secret_ref to reference environment variables:

[[sources]]
name = "Production Logs"
host = "clickhouse:9000"
username = "logchef"
secret_ref = "LOGCHEF_CH_PROD_PASSWORD"
database = "logs"
table_name = "otel_logs"

Set the environment variable before starting Logchef:

Terminal window
export LOGCHEF_CH_PROD_PASSWORD="actual-password"

For Nomad deployments, use Nomad variables with template blocks:

password = "{{ "{{.ch_prod_password}}" }}"

When you first enable provisioning on an existing Logchef instance, resources declared in config are matched against existing database records by name:

  • A source named “Production Logs” in config matches an existing source named “Production Logs” in the DB
  • Matched resources are adopted (marked as managed) and updated to match config
  • Unmatched config entries create new resources

No special migration flag is needed — adoption happens automatically on name match.

With prune = false (default), managed resources removed from config are kept but logged as warnings:

WARN managed source not in config (prune=false, keeping) name="Old Source"

With prune = true, they are deleted. Be careful:

Managed resources cannot be modified via the API or UI. Attempting to edit or delete a managed team/source/user returns:

{
"status": "error",
"message": "This source is managed by provisioning config and cannot be modified via API",
"error_type": "ManagedResourceError"
}

Admins can export the current database state as a provisioning config via the API:

Terminal window
curl -s https://logchef.example.com/api/v1/admin/provisioning/export \
-H "Authorization: Bearer <token>" | jq .

This returns a JSON representation of all sources, teams, and memberships — useful as a starting point for writing your provisioning.toml.

You can define provisioning inline in config.toml or as a separate file:

Separate file (recommended):

config.toml
[provisioning]
file = "provisioning.toml"

Inline:

config.toml
[provisioning]
manage_sources = true
manage_teams = true
[[provisioning.sources]]
name = "My Logs"
# ...

The separate file approach keeps secrets isolated and makes the provisioning config independently deployable.