CREATE SECRET
MotherDuck lets you store your cloud storage credentials and other sensitive values for convenience, using the familiar DuckDB CREATE SECRET syntax. See DuckDB CREATE SECRET documentation.
Ensure you add the PERSISTENT or IN MOTHERDUCK keyword to create MotherDuck secrets. Secrets stored in MotherDuck are fully encrypted and scoped to the user who created them. They are not shared with other users in your organization.
You can use the PERSISTENT keyword to create a local file persistent secret in local DuckDB as well. It gets stored unencrypted in the ~/.duckdb/stored_secrets directory.
When you've loaded the MotherDuck extension, PERSISTENT secrets are stored encrypted in MotherDuck. Locally persisted secrets are not impacted.
You can still create locally persisted secrets when using MotherDuck by specifying the secret storage backend: CREATE SECRET IN LOCAL_FILE.
When using MotherDuck, the statement below creates a cloud-persistent secret stored in MotherDuck.
Syntax
CREATE [OR REPLACE] (PERSISTENT SECRET [secret_name] | SECRET [secret_name] IN MOTHERDUCK)
(
TYPE <S3 | GCS | R2 | AZURE | HUGGINGFACE | ICEBERG | FLIGHTS>,
<storage-specific properties>
);
Secret parameters
Supported parameters for S3, GCS, and R2 secrets:
| Name | Description | Secret | Type | Default |
|---|---|---|---|---|
| ENDPOINT | Specify a custom S3 endpoint | S3, GCS, R2 | STRING | s3.amazonaws.com for S3 |
| KEY_ID | The ID of the key to use | S3, GCS, R2 | STRING | - |
| REGION | The region used for authentication. For S3, this should match the region of the bucket. For R2, use auto since R2 buckets are regionless. | S3, GCS, R2 | STRING | Orgs will default to the region that was chosen at signup: us-east-1, us-west-2, eu-central-1, or eu-west-1. For R2, defaults to auto. |
| SECRET | The secret of the key to use | S3, GCS, R2 | STRING | - |
| SESSION_TOKEN | Optionally, a session token can be passed to use temporary credentials | S3, GCS, R2 | STRING | - |
| URL_COMPATIBILITY_MODE | Can help when URLs contain problematic characters | S3, GCS, R2 | BOOLEAN | true |
| URL_STYLE | Either vhost or path | S3, GCS, R2 | STRING | vhost for S3, path for R2 and GCS |
| USE_SSL | Whether to use HTTPS or HTTP | S3, GCS, R2 | BOOLEAN | true |
| ACCOUNT_ID | The R2 account ID to use for generating the endpoint URL | R2 | STRING | - |
| KMS_KEY_ID | AWS KMS (Key Management Service) key for Server Side Encryption S3 | S3 | STRING | - |
| SCOPE | Scope of secret resolution; In the case of multiple matching secrets, the longest prefix is chosen | S3, GCS, R2 | STRING | - |
Because of SSL certificate verification requirements, S3 bucket names that contain dots (.) cannot be accessed using vhost style URLs. This is due to AWS's SSL wildcard certificate (*.s3.amazonaws.com) which only validates single-level subdomains. To resolve this SSL issue, use URL_STYLE path in your secret.
Examples
Manually defined S3 secret
To manually create an S3 secret in MotherDuck:
CREATE SECRET IN MOTHERDUCK (
TYPE S3,
KEY_ID 's3_access_key',
SECRET 's3_secret_key',
REGION 'us-east-1',
SCOPE 'my-bucket-path'
);
This creates a new secret with a default name (for S3, __default_s3) and a default scope (i.e., [s3://, s3n://, s3a://]) used for path matching explained below.
DuckDB uses the SCOPE parameter to determine which secret to use. When using persistent secrets or public buckets, scoping the secrets is important so that the database uses the correct secret. Imprecise scoping will lead to authentication errors.
Learn more in the DuckDB documentation.
Secret providers
MotherDuck supports the same secret providers as DuckDB.
To create a secret by automatically fetching credentials using mechanisms provided by the AWS SDK, see AWS CREDENTIAL_CHAIN provider.
To create a secret by automatically fetching credentials using mechanisms provided by the Azure SDK, see Azure CREDENTIAL_CHAIN provider.
To create a secret by automatically fetching credentials using mechanisms provided by the Hugging Face CLI, see Hugging Face CREDENTIAL_CHAIN provider.
To store a secret from a given secret provider in MotherDuck, specify the PERSISTENT or IN MOTHERDUCK keyword in addition.
Provider examples
If you are logged in to a provider on your local machine you can use those credentials to connect to the bucket. Creating the secret does not work in the MotherDuck UI since your credential provider is not available there, but you can use the secret once it's stored.
To store a secret configured through aws configure:
CREATE PERSISTENT SECRET aws_secret (
TYPE S3,
PROVIDER CREDENTIAL_CHAIN
);
To store a secret using AWS SSO credentials:
-- if you use AWS SSO, run `aws sso login --profile <your_sso_profile>` first
CREATE SECRET aws_secret IN MOTHERDUCK (
TYPE S3,
PROVIDER CREDENTIAL_CHAIN,
CHAIN 'sso',
PROFILE '<your_sso_profile>'
);
Starting with DuckDB v1.4.0, credentials are validated at secret creation time. If your credentials are not resolvable locally (for example, expired SSO tokens or missing ~/.aws/credentials), CREATE SECRET will fail with a Secret Validation Failure error. The recommended fix is to use the correct CHAIN and PROFILE for your credential type (see the SSO example above) and confirm your SSO session is active. If you need to bypass local validation, you can add VALIDATION 'none', but keep in mind that this skips the local check that confirms your credentials are valid before storing them in MotherDuck.
To store a secret configured through az configure:
CREATE SECRET azure_secret IN MOTHERDUCK (
TYPE AZURE,
PROVIDER CREDENTIAL_CHAIN,
ACCOUNT_NAME 'some-account'
);
Iceberg secrets
Secrets with TYPE ICEBERG hold the credentials for an Iceberg REST catalog. Reference the secret by name when you attach the catalog with CREATE DATABASE (TYPE ICEBERG, "secret" <secret_name>, ...).
-- OAuth2 client credentials
CREATE SECRET my_iceberg_secret IN MOTHERDUCK (
TYPE ICEBERG,
CLIENT_ID 'my_client_id',
CLIENT_SECRET 'my_client_secret',
OAUTH2_SERVER_URI 'https://my-catalog.example.com/v1/oauth/tokens'
);
-- Bearer token
CREATE SECRET my_iceberg_secret IN MOTHERDUCK (
TYPE ICEBERG,
TOKEN 'my_bearer_token'
);
Common Iceberg secret parameters:
| Name | Description |
|---|---|
| CLIENT_ID | OAuth2 client ID |
| CLIENT_SECRET | OAuth2 client secret |
| OAUTH2_SERVER_URI | OAuth2 token endpoint that issues the catalog access token |
| OAUTH2_SCOPE | OAuth2 scope requested when fetching the token |
| TOKEN | Bearer token, as an alternative to OAuth2 credentials |
| ENDPOINT | Iceberg REST catalog URL. Set here or in the CREATE DATABASE options |
For Amazon S3 Tables, authenticate with an S3 secret instead and set endpoint_type 's3_tables' in the database options. See Amazon S3 Tables.
Create Iceberg secrets with the IN MOTHERDUCK or PERSISTENT keyword so they're stored in MotherDuck and available to the server-side catalog attachment.
Flight secrets
Secrets with TYPE FLIGHTS hold key-value pairs for Flights — API keys, connection strings, or any other sensitive values your Flight code needs at runtime. Pass the pairs as a DuckDB MAP in the PARAMS parameter:
CREATE SECRET flight_secret IN MOTHERDUCK (
TYPE FLIGHTS,
PARAMS MAP {
'API_KEY': '<your_api_key>',
'ENDPOINT': 'https://api.example.com'
}
);
Create Flight secrets with the IN MOTHERDUCK or PERSISTENT keyword — they're read by the MotherDuck-managed Flight runtime, so they must be stored in MotherDuck.
See the flight_secret_names parameter in MD_CREATE_FLIGHT for guidance on attaching secrets to Flights, environment variable names at runtime, and when to use secrets instead of the Flight's config map.
Querying with secrets
Secret scope is supported in the same way as in DuckDB to allow multiple secrets of the same type to be stored in MotherDuck. When there are multiple local (i.e. in memory and store in local file) and remote (i.e. MotherDuck) secrets of the same type, scope matching (secret scope against the file path) happens to determine which secret to use to open a file. Both local and remote secrets are considered in scope matching.
In the case of multiple matching secrets, the secret with the longest matching scope prefix is chosen.
In the case of multiple secrets stored in different secret storages sharing the same scope (e.g. the default scope if not specified), matching secret is chosen based on the following order: local temp secret > local_file secret > MotherDuck secret.
When you query cloud storage (S3, GCS, Azure, R2) while connected to MotherDuck, the query is routed to MotherDuck's cloud execution engine, not your local machine. MotherDuck can use any matching secret to authenticate with your storage provider, including temporary, in-memory secrets from your local DuckDB session. Your local DuckDB client does not connect to cloud storage directly.
To see which secret (either local or remote) is being used by MotherDuck, the DuckDB which_secret table function can be used, which takes a path and the secret type.
Example usage
To see which secret is used to open a file:
FROM which_secret('s3://my-bucket/my_dataset.parquet', 's3');
┌───────────────────────┬────────────┬────────────┐
│ name │ persistent │ storage │
│ varchar │ varchar │ varchar │
├───────────────────────┼────────────┼────────────┤
│ __default_s3 │ PERSISTENT │ motherduck │
└───────────────────────┴────────────┴────────────┘
Discovering buckets and files
If you want to inspect cloud storage from SQL before querying files directly:
- Use
MD_LIST_BUCKETS_FOR_SECRET()to list buckets visible to an S3/AWS secret. - Use
MD_LIST_FILES()to list files ins3://,azure://, oraz://paths.
MD_LIST_FILES() supports S3 and Azure paths only. It does not accept r2://, gcs://, or gs:// paths.
Troubleshooting
If you encounter issues creating or using secrets, check out our troubleshooting guides:
- AWS S3 Secrets Troubleshooting - Common issues with AWS S3 authentication and credentials
- Error Messages - Understanding MotherDuck error messages