Skip to content

Sources

Sources define where a board reads data from. Most projects use one warehouse connection for SQL queries, but a board can also read files, HTTP endpoints, inline values, dbt models, or MetricFlow metrics.

Connection sources are defined once, in the project's root dataface.yml, as a named sources: registry. A face (or faces/meta.yaml) never defines a connection inline — it only references a source by name:

# dataface.yml
sources:
  analytics:
    type: dbt_profile
    profile: my_dbt_project
    target: dev
source: analytics   # References the "analytics" source above

queries:
  sales: SELECT * FROM orders

Every sources: block on this page belongs in dataface.yml, not in a face. A face's own source: field always holds a name (or, for a single colocated data file, an inline path — see Inline File Sources), never a connection definition.

Dataface sources: are connection definitions. They are separate from dbt sources: resources, which document raw tables inside a dbt project. If you are setting up dbt source tables, use dbt's source properties reference.

Source Types

For warehouse-backed SQL, Dataface uses dbt-compatible connection settings. In most dbt projects, use type: dbt_profile and let dbt own the adapter-specific credentials. Direct warehouse source types use the same field names as dbt profiles, but they are flat because boards read data; they do not build dbt models.

You do not need profiles.yml for direct sources such as postgres, snowflake, bigquery, duckdb, or sqlite. Dataface uses the direct source block as the connection config. The dbt links below are still useful because they document the same adapter credential fields.

Source Dataface setup Credential fields / setup
Existing dbt project type: dbt_profile dbt profiles.yml
BigQuery type: bigquery BigQuery connection
DuckDB type: duckdb DuckDB connection
Postgres type: postgres Postgres connection
Redshift type: redshift Redshift connection
Snowflake type: snowflake Snowflake connection
MySQL / MariaDB type: mysql dbt community adapter; start with supported data platforms
SQLite type: sqlite Dataface direct source; no dbt setup
Databricks type: dbt_profile Databricks connection
Spark type: dbt_profile Apache Spark connection
dbt models dbt_model query with a dbt profile source dbt profiles.yml
MetricFlow metrics metricflow query with a dbt profile source MetricFlow
CSV files type: csv Files and APIs
Parquet files type: parquet Files and APIs
JSON files type: json Files and APIs
HTTP endpoints type: http query Files and APIs
Inline static data type: values query No source setup

dbt Profile Sources

Dataface can either read your warehouse credentials from a dbt profile or accept a direct source definition with dbt-style field names.

Use dbt_profile when your project already has profiles.yml:

# dataface.yml
sources:
  analytics:
    type: dbt_profile
    profile: my_dbt_project
    target: dev

Dataface resolves profiles.yml in this order:

  1. profiles_dir on the source config
  2. DBT_PROFILES_DIR
  3. Project root, next to dataface.yml or dbt_project.yml
  4. ~/.dbt/profiles.yml

If none of those locations contains profiles.yml, Dataface raises an error.

Direct Warehouse Sources

Direct warehouse sources are useful for small projects that do not share a dbt project. This is the full connection config; no profiles.yml file is required. For larger dbt projects, prefer type: dbt_profile.

Postgres

# dataface.yml
sources:
  analytics:
    type: postgres
    host: "{{ env_var('ANALYTICS_HOST') }}"
    port: 5432
    dbname: analytics
    schema: public
    user: "{{ env_var('ANALYTICS_USER') }}"
    password: "{{ env_var('ANALYTICS_PASSWORD') }}"

DuckDB

# dataface.yml
sources:
  local_db:
    type: duckdb
    path: ./data/analytics.duckdb
    schema: crm

SQLite

# dataface.yml
sources:
  local_sqlite:
    type: sqlite
    path: ./data/analytics.sqlite

Files and APIs

CSV, Parquet, JSON, and HTTP sources do not need dbt. They are simpler local Dataface source definitions for examples, prototypes, and lightweight external data.

CSV

A CSV source is a namespace of relations. Each key under files: is a table name; the value is the path to the CSV file relative to the project root.

# dataface.yml
sources:
  sales_csv:
    type: csv
    files:
      sales: assets/data/sales.csv

Then query it by name:

queries:
  sales:
    source: sales_csv
    sql: SELECT * FROM sales

A single source can expose multiple CSV files as separate tables:

# dataface.yml
sources:
  sales_data:
    type: csv
    files:
      orders: assets/data/orders.csv
      returns: assets/data/returns.csv

JSON

# dataface.yml
sources:
  product_json:
    type: json
    files:
      products: assets/data/products.json
queries:
  products:
    source: product_json
    sql: SELECT * FROM products

Parquet

# dataface.yml
sources:
  events:
    type: parquet
    files:
      events: assets/data/events.parquet
queries:
  event_counts:
    source: events
    sql: SELECT * FROM events

HTTP

Unlike SQL and file queries, an HTTP query is self-contained: set url: (and optional headers:, method:, body:) directly on the query. It has no source: field — there is no named registry entry to reference.

queries:
  forecast:
    type: http
    url: "https://api.example.com/forecast"

See Queries for the full HTTP query field reference.

Inline File Sources

A single CSV, JSON, or Parquet file that only one query reads doesn't need a named registry entry — reference the file directly on source:, as a path containing / or ending in a data-file extension:

queries:
  sales:
    source: ./data/sales.csv
    sql: SELECT * FROM sales

The path resolves relative to the face file's own directory. The table name is the file's stem (sales.csv → table sales); a stem that isn't a valid SQL identifier is a compile error rather than a silently sanitized name — rename the file or use the named-registry form below. Only a single file is allowed inline (no files: list); an inline file source is never a Cloud-managed source (no permissions, no connection binding — it's materialized straight from the file's git content).

Use the named-registry form (type: csv/json/parquet with a files: map in dataface.yml, above) instead when a file is shared across faces or a source exposes more than one file as separate tables.

Source Defaults

Set source: on a face to make all queries in that board use a default source by name. A faces/meta.yaml (or a directory's own meta.yaml) can set the same field to default every face beneath it:

source: finance

queries:
  monthly_revenue:
    sql: SELECT month, revenue FROM finance_revenue

  sales_pipeline:
    source: sales
    sql: SELECT stage, amount FROM sales_pipeline

Sources are resolved from most specific to broadest:

  1. Query-level source:
  2. Face-level source:
  3. The nearest ancestor source: in the faces/meta.yaml cascade

An unknown source name is a validation error.

Environment Variables

Use env_var() in source configuration to keep credentials out of YAML files:

# dataface.yml
sources:
  analytics:
    type: postgres
    host: "{{ env_var('DB_HOST', 'localhost') }}"
    user: "{{ env_var('DB_USER') }}"
    password: "{{ env_var('DB_PASSWORD') }}"

Store credentials in .env or your deployment environment:

DB_HOST=localhost
DB_USER=analytics_user
DB_PASSWORD=secret123

Keep credentials out of faces

env_var() is for source configuration. Do not put secrets in board YAML, query text, or rendered output.

Read-only Posture

Dataface boards read data. They never intentionally write to your warehouse, but connection-level enforcement depends on the source type.

DuckDB and SQLite are opened with driver-level read-only settings. Every other warehouse should use credentials that can only read data. Dataface also applies an in-process SQL allowlist before execution, but SELECT-only credentials are the warehouse-side defense.

Warehouse In-process enforcement Recommended operator posture
DuckDB Driver read-only mode Handled by Dataface
SQLite Driver read-only URI mode Handled by Dataface
Postgres SQL allowlist only SELECT-only role
MySQL / MariaDB SQL allowlist only SELECT-only user
Snowflake SQL allowlist only SELECT-only role
BigQuery SQL allowlist only roles/bigquery.dataViewer or equivalent
Redshift SQL allowlist only SELECT-only IAM role or database user
dbt profile sources Depends on adapter SELECT-only profile credential

File access from SQL

dft serve runs strictly read-only: author SQL cannot reach the filesystem or network through DuckDB, so functions like read_csv(...), read_json_auto(...), read_parquet(...), and httpfs are not available in query SQL. Point data at a file source instead — declare it with type: csv, type: json, or type: parquet and a files: mapping (see Files and APIs), then query the table by name. Dataface parses the file and loads it for querying without granting SQL any file access.

If a local dashboard genuinely needs to read files directly in SQL — for example glob analytics like read_json_auto('runs/*/report.json') that cannot be expressed as a fixed files: mapping — start the server with dft serve --allow-external-access to opt that instance back into DuckDB file access. Leave it off for anything served to others.

  • Queries for SQL, values, file, HTTP, dbt model, and MetricFlow query types
  • MetricFlow for semantic-layer queries
  • Quick Guide for the shortest syntax overview