Configuration Reference¶
Complete reference for all Dango configuration files and schemas.
Overview¶
Dango uses several configuration files organized across three directories:
| File | Purpose | Sensitive | User-Edited |
|---|---|---|---|
.dango/project.yml | Project metadata, platform settings, auth config | No | Yes |
.dango/sources.yml | Data source definitions | No | Yes |
.dango/schedules.yml | Scheduled sync/dbt jobs and notifications | No | Yes |
.dango/monitors.yml | Metric monitoring and alert definitions | No | Yes |
.dango/cloud.yml | Cloud deployment state | No | Rarely |
.dango/pii-overrides.yml | PII column override decisions | No | Yes |
.dango/metabase.yml | Metabase admin credentials and database ID | Yes | No |
.env | Environment variables | Yes | Yes |
.dlt/secrets.toml | Source API keys and OAuth tokens | Yes | Yes |
.dlt/config.toml | Non-sensitive dlt parameters | No | Rarely |
dbt/profiles.yml | DuckDB connection config for dbt | No | No |
dbt/dbt_project.yml | dbt project config | No | Rarely |
docker-compose.yml | Metabase container config | No | No |
.dango/project.yml¶
Project metadata, platform settings, and authentication configuration. Created by dango init.
project Section¶
project:
name: my-analytics
organization: Acme Corp
dango_version: 1.0.0b1
created: '2026-01-15T10:30:00'
created_by: [email protected]
purpose: Track sales performance and customer behavior
stakeholders:
- name: Sarah Chen
role: CMO - Dashboard user
contact: [email protected]
sla: Daily by 9am UTC
limitations: Stripe data has 24h delay
getting_started: |
1. Run 'dango sync'
2. Open http://localhost:8800
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Project name |
organization | string | No | Organization name |
dango_version | string | No | Dango version used to create the project |
created | datetime | Yes | Creation timestamp (auto-populated) |
created_by | string | Yes | Creator email or name |
purpose | string | Yes | Why this project exists |
stakeholders | list | No | Project stakeholders (each with name, role, contact) |
sla | string | No | Data freshness SLA |
limitations | string | No | Known limitations or caveats |
getting_started | string | No | Quick start guide for new team members |
platform Section¶
platform:
duckdb_path: ./data/warehouse.duckdb
dbt_project_dir: ./dbt
data_dir: ./data
port: 8800
metabase_port: 3000
dbt_docs_port: 8081
marimo_port: 7805
auto_sync: true
auto_dbt: true
debounce_seconds: 600
dbt_coalesce_seconds: 10
workers: null
watch_patterns:
- '*.csv'
- '*.json'
- '*.jsonl'
- '*.ndjson'
- '*.parquet'
watch_directories:
- data/uploads
| Field | Type | Default | Description |
|---|---|---|---|
duckdb_path | string | ./data/warehouse.duckdb | Path to DuckDB database |
dbt_project_dir | string | ./dbt | Path to dbt project |
data_dir | string | ./data | Data directory path |
port | integer | 8800 | Web UI and API port |
metabase_port | integer | 3000 | Metabase dashboard port |
dbt_docs_port | integer | 8081 | dbt documentation port |
marimo_port | integer | 7805 | Marimo notebooks port |
auto_sync | boolean | true | Auto-sync when watched files change |
auto_dbt | boolean | true | Auto-run dbt after sync completes |
debounce_seconds | integer | 600 | Seconds to wait before triggering auto-sync (10 min) |
dbt_coalesce_seconds | integer | 10 | Seconds to wait before dbt run (coalesces multiple syncs) |
workers | integer | null | Uvicorn worker count (null = 1). Single worker is the default for both local and cloud. |
watch_patterns | list[string] | ["*.csv", "*.json", "*.jsonl", "*.ndjson", "*.parquet"] | Glob patterns for file watch |
watch_directories | list[string] | ["data/uploads"] | Directories to watch (relative to project root) |
auth Section¶
auth:
enabled: true
idle_timeout_minutes: 1440 # 24 hours
session_max_days: 365 # 1 year
password_max_age_days: 0 # disabled (0 = no forced rotation)
require_2fa: false
rate_limit:
enabled: true
login:
requests: 10
window_seconds: 60
api:
requests: 200
window_seconds: 60
trusted_proxies: []
lockout:
max_attempts: 5
lockout_minutes: 15
oauth_providers: {}
| Field | Type | Default | Description |
|---|---|---|---|
enabled | boolean | true | Enable authentication |
idle_timeout_minutes | integer | 1440 (24h) | Session idle timeout in minutes |
session_max_days | integer | 365 (1 year) | Maximum session lifetime in days |
password_max_age_days | integer | 0 (disabled) | Force password change after this many days. 0 disables rotation. When expired, user is redirected to the change-password page on next login. OAuth login bypasses rotation. |
require_2fa | boolean | false | Require all users to set up TOTP 2FA |
rate_limit.enabled | boolean | true | Enable rate limiting |
rate_limit.login.requests | integer | 10 | Max login attempts per window |
rate_limit.login.window_seconds | integer | 60 | Login rate limit window |
rate_limit.api.requests | integer | 200 | Max API requests per window |
rate_limit.api.window_seconds | integer | 60 | API rate limit window |
rate_limit.trusted_proxies | list[string] | [] | IPs of trusted reverse proxies |
lockout.max_attempts | integer | 5 | Failed attempts before lockout |
lockout.lockout_minutes | integer | 15 | Lockout duration in minutes |
oauth_providers | dict | {} | OAuth login providers (keyed by google, github) with client_id and client_secret |
Cloud deployment defaults differ
During dango deploy, the auth section is configured with shorter timeouts for security: idle_timeout_minutes: 60 and session_max_days: 30.
api Section¶
| Field | Type | Default | Description |
|---|---|---|---|
query_max_rows | integer | 10000 | Maximum rows returned by POST /api/query. Increase for scheduled reporting scripts pulling large datasets. |
query_timeout_seconds | integer | 30 | Query timeout in seconds. Increase for complex analytical queries. |
.dango/sources.yml¶
Data source definitions and configuration. Managed via dango source add or manual editing.
Structure¶
version: '1.0'
sources:
- name: source_name
type: source_type
enabled: true
description: Human-readable description
tags: [tag1, tag2]
lookback_days: 7
# Type-specific config block (one of the options below)
Common Fields¶
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
name | string | Yes | -- | Unique source name (lowercase alphanumeric + underscore) |
type | SourceType | Yes | -- | Source type (see Source Registry) |
enabled | boolean | No | true | Whether to include in syncs |
description | string | No | -- | Human-readable description |
tags | list[string] | No | [] | Metadata tags |
lookback_days | integer | No | -- | Re-load this many days on incremental sync |
Type-Specific Configuration¶
Each source type has its own configuration block. Sources with a dedicated Pydantic model use a typed config key (e.g., stripe:, hubspot:). Sources without a dedicated model use generic_config:.
Typed config examples:
# Stripe
- name: stripe_payments
type: stripe
stripe:
stripe_secret_key_env: STRIPE_API_KEY
endpoints: [charges, customers, invoices]
start_date: '2024-01-01'
# HubSpot
- name: hubspot_crm
type: hubspot
hubspot:
api_key_env: HUBSPOT_API_KEY
resources: [contacts, companies, deals]
# GitHub
- name: my_repo
type: github
github:
access_token_env: GITHUB_ACCESS_TOKEN
owner: my-org
name: my-repo
# Slack
- name: slack_data
type: slack
slack:
access_token_env: SLACK_ACCESS_TOKEN
selected_channels: [C01234ABCDE]
generic_config example (21+ source types):
# Zendesk (uses generic_config)
- name: zendesk_support
type: zendesk
generic_config:
subdomain: mycompany
email: [email protected]
For the complete list of source types, typed config fields, and which sources use generic_config, see the Source Registry.
.dango/schedules.yml¶
Scheduled sync and dbt jobs with notification configuration. Managed via dango schedule add or manual editing.
Structure¶
schedules:
- name: hourly_sync
type: sync
cron: every_hour
sources: [stripe_payments, hubspot_crm]
enabled: true
timezone: America/New_York
notify_on: [failure, stale]
- name: daily_transforms
type: dbt
cron: daily
dbt_command: dbt run
enabled: true
notifications:
webhooks:
- name: slack_alerts
url: https://hooks.slack.com/services/T.../B.../xxx
format: slack
- name: generic_webhook
url: https://api.example.com/webhook
format: generic
on_failure: true
on_success: true
on_stale: true
on_governance: true
on_analysis: true
stale_threshold_hours: 24
Schedule Fields¶
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
name | string | Yes | -- | Schedule name (lowercase alphanumeric + underscore, starts with letter) |
type | ScheduleType | No | sync | Schedule type: sync, sync_only, dbt |
cron | string | Yes | -- | Cron expression or preset name |
sources | list[string] | Yes* | -- | Source names to sync (*required for sync/sync_only types) |
enabled | boolean | No | true | Enable this schedule |
timezone | string | No | server TZ | Timezone for cron evaluation |
start_date | datetime | No | -- | First execution date |
misfire_grace_time | integer | No | -- | Seconds to wait before skipping missed execution |
timeout_minutes | integer | No | -- | Execution timeout |
notify_on | list[string] | No | [] | Override notification triggers: failure, success, stale |
dbt_command | string | No* | -- | dbt command to run (*required for dbt type) |
Schedule Types¶
| Type | Behavior |
|---|---|
sync | Sync selected sources, then run dbt (recommended) |
sync_only | Sync selected sources without running dbt afterward |
dbt | Run a dbt command only (no sync) |
Cron Presets¶
| Preset | Cron Expression | Description |
|---|---|---|
every_15m | */15 * * * * | Every 15 minutes |
every_hour | 0 * * * * | Top of every hour |
every_6h | 0 */6 * * * | Every 6 hours |
daily | 0 6 * * * | Daily at 6 AM |
weekly | 0 6 * * 1 | Monday at 6 AM |
You can also use standard 5-field cron expressions (e.g., 30 2 * * * for 2:30 AM daily).
CLI Frequency Choices¶
The dango schedule add wizard offers these frequencies:
| Label | Code |
|---|---|
| Every hour | 1h |
| Every 2 hours | 2h |
| Every 3 hours | 3h |
| Every 4 hours | 4h |
| Every 6 hours | 6h |
| Every 8 hours | 8h |
| Every 12 hours | 12h |
| Daily | daily |
| Weekly | weekly |
| Custom cron | custom |
Notification Fields¶
| Field | Type | Default | Description |
|---|---|---|---|
webhooks | list | [] | Webhook endpoints |
webhooks[].name | string | -- | Webhook name |
webhooks[].url | string | -- | Webhook URL (must start with http:// or https://) |
webhooks[].format | string | generic | Message format: generic or slack |
on_failure | boolean | true | Notify on sync failure |
on_success | boolean | true | Notify on sync completion |
on_stale | boolean | true | Notify on stale data |
on_governance | boolean | true | Notify on governance events (schema drift, PII) |
on_analysis | boolean | true | Notify on metric alerts |
stale_threshold_hours | integer | 24 | Hours before data is considered stale |
Webhook Payload (Wire Format)¶
The generic webhook sends JSON with these fields:
{
"event": "sync_completed",
"schedule": "hourly_sync",
"sources": ["stripe_payments"],
"error": null,
"duration_seconds": 45.2,
"timestamp": "2026-05-17T12:34:56+00:00",
"dashboard_url": "http://localhost:8800",
"rows_loaded": 1523,
"stale_hours": null,
"attempt_number": null,
"next_retry_at": null,
"metadata": null
}
Wire format field mapping
The webhook payload uses different field names than the internal Pydantic model: event_type becomes event, schedule_name becomes schedule, occurred_at becomes timestamp.
Event types: sync_completed, sync_failed, sync_stale, sync_retrying, schema_drift_detected, pii_detected, metric_alert
.dango/monitors.yml¶
Metric monitoring and alert definitions. Managed via manual editing.
Structure¶
enabled: true
monitors:
- name: daily_revenue
source_table: raw_stripe.charges
value_expression: "SUM(amount) / 100.0"
filter: "status = 'succeeded'"
compare: week_over_week
alert_threshold: 20.0
drill_down: [currency]
- name: new_customers
source_table: raw_hubspot.contacts
value_expression: "COUNT(*)"
compare: rolling_7day_avg
alert_threshold: 30.0
Monitor Fields¶
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
name | string | Yes | -- | Monitor name (lowercase alphanumeric + underscore) |
source_table | string | Yes | -- | Schema-qualified table (schema.table) |
value_expression | string | Yes | -- | SQL expression for metric value |
filter | string | No | -- | SQL WHERE clause filter |
compare | ComparisonType | No | week_over_week | Comparison strategy |
alert_threshold | float | No | -- | Percentage change threshold for alerts |
drill_down | list[string] | No | [] | Columns for drill-down (GROUP BY) |
Top-Level Fields¶
| Field | Type | Default | Description |
|---|---|---|---|
enabled | boolean | true | Enable metric monitoring |
Comparison Types¶
| Type | Description |
|---|---|
week_over_week | Compare current value to same day last week |
rolling_7day_avg | Compare to 7-day rolling average |
rolling_30day_avg | Compare to 30-day rolling average |
prior_period | Compare to the previous period |
Backward compatibility
The file can also be named .dango/metrics.yml. The monitors key accepts metrics as an alias, and alert_threshold accepts warn_threshold.
.dango/cloud.yml¶
Cloud deployment state. Created by dango deploy and updated by deployment operations. Generally not edited manually.
Structure¶
provider: digitalocean
droplet_id: 123456789
droplet_ip: 203.0.113.10
firewall_id: abcdef-1234-5678
region: nyc1
size: s-2vcpu-4gb
domain: analytics.example.com
ssh_key_path: .dango/cloud_key
ssh_key_id: 12345678
deploy_branch: main
spaces:
bucket: my-backups
region: nyc3
access_key_env: SPACES_ACCESS_KEY
secret_key_env: SPACES_SECRET_KEY
dbt_overrides:
threads: 2
memory_limit: 1GB
Fields¶
| Field | Type | Default | Description |
|---|---|---|---|
provider | string | digitalocean | Deployment provider: digitalocean or byos |
droplet_id | integer | -- | DigitalOcean droplet ID (set after provisioning) |
droplet_ip | string | -- | Public IP address (set after provisioning) |
firewall_id | string | -- | DigitalOcean firewall ID |
region | string | nyc1 | DigitalOcean region |
size | string | s-2vcpu-4gb | Droplet size slug |
domain | string | -- | Custom domain name |
ssh_key_path | string | .dango/cloud_key | Path to SSH private key |
ssh_key_id | integer | -- | DigitalOcean SSH key ID |
deploy_branch | string | main | Expected git branch for deployments |
spaces.bucket | string | -- | Spaces bucket name (required if spaces configured) |
spaces.region | string | droplet region | Spaces region |
spaces.access_key_env | string | SPACES_ACCESS_KEY | Env var for Spaces access key |
spaces.secret_key_env | string | SPACES_SECRET_KEY | Env var for Spaces secret key |
dbt_overrides.threads | integer | vCPU count | Override dbt threads |
dbt_overrides.memory_limit | string | 25% of RAM | Override DuckDB memory limit |
.dango/pii-overrides.yml¶
Override PII detection results for specific columns. When automatic PII scanning produces false positives or misses sensitive data, add overrides here.
Structure¶
overrides:
- source: stripe_payments
table: charges
column: customer_email
status: pii
set_by: [email protected]
reason: Contains customer email addresses
updated_at: '2026-05-17T12:34:56'
- source: hubspot_crm
table: companies
column: company_name
status: not_pii
set_by: [email protected]
reason: Public company names, not personally identifiable
updated_at: '2026-05-17T12:35:00'
Fields¶
| Field | Type | Description |
|---|---|---|
source | string | Source name |
table | string | Table name |
column | string | Column name |
status | string | PII status: pii or not_pii |
set_by | string | User who set the override |
reason | string | Human-readable reason |
updated_at | datetime | ISO-8601 timestamp |
.dango/metabase.yml¶
Metabase admin credentials and database reference. Auto-generated during Metabase setup. Contains sensitive credentials.
Sensitive file
This file contains the Metabase admin password. It is gitignored by default. Do not commit it to version control.
Structure¶
| Field | Type | Description |
|---|---|---|
admin.email | string | Metabase admin email |
admin.password | string | Metabase admin password (auto-generated) |
database.id | integer | DuckDB database ID in Metabase |
.env¶
Environment variables for the project. Loaded automatically by Dango.
See the Environment Variables Reference for the complete list of supported variables.
.dlt/secrets.toml¶
Sensitive credentials for dlt sources. Auto-populated by dango source add and dango oauth flows.
Security
This file is automatically gitignored. Never commit credentials to version control.
Structure¶
[sources.{source_name}]
api_key = "your-api-key"
[sources.{source_name}.credentials]
client_id = "..."
client_secret = "..."
refresh_token = "..."
Common Patterns¶
# Stripe
[sources.stripe_payments]
api_key = "sk_live_51ABCdef..."
# Google Sheets (OAuth)
[sources.budgets]
[sources.budgets.credentials]
client_id = "123456789.apps.googleusercontent.com"
client_secret = "GOCSPX-abc123..."
refresh_token = "1//0abc123..."
# Facebook Ads
[sources.facebook_marketing]
access_token = "EAAB123..."
account_id = "123456789"
# HubSpot
[sources.hubspot_crm]
api_key = "pat-na1-xxxxxxxxxxxxx"
# PostgreSQL
[sources.postgres_prod]
connection_string = "postgresql://user:[email protected]:5432/production"
# GitHub
[sources.my_repo]
access_token = "ghp_xxxxxxxxxxxxx"
.dlt/config.toml¶
Non-sensitive dlt configuration. Safe to commit to version control.
Structure¶
dbt/profiles.yml¶
Standard dbt connection profile for DuckDB. Auto-generated by dango init.
Auto-generated
This file is managed by Dango. Manual edits may be overwritten by dango init or cloud deployment.
dbt/dbt_project.yml¶
Standard dbt project configuration. Auto-generated by dango init.
name: dango
version: '1.0.0'
config-version: 2
profile: dango
model-paths: ["models"]
analysis-paths: ["analyses"]
test-paths: ["tests"]
seed-paths: ["seeds"]
macro-paths: ["macros"]
snapshot-paths: ["snapshots"]
Auto-generated
This file is managed by Dango. Custom dbt models are placed in dbt/models/.
docker-compose.yml¶
Metabase container configuration. Generated from a template during dango start.
Auto-generated
This file is generated from a Jinja2 template and should not be edited manually. It is regenerated on each dango start.
Validation¶
Validate your configuration files:
# Validate all config files
dango validate
# Validate specific config
dango config validate
# Show current configuration
dango config show
Related Pages¶
- Environment Variables --- Complete variable reference
- Permissions Matrix --- Role-based access control
- Source Registry --- All source types and their config fields
- CLI Reference --- Config management commands