Configuration
Piddiplatsch loads configuration in this order, with each existing file overriding values from the preceding layer:
- packaged
src/piddiplatsch/config/default.toml - site-wide
/etc/piddi/piddi.toml - local
./custom.toml
Missing optional site and local files are ignored. An explicit --config PATH
must name an existing file; a missing file or directory is an error. Keep credentials in the
local ignored file. --config PATH replaces the third layer with the selected
file; the packaged and site-wide layers are still loaded first.
Start with a small site override
Copy etc/esgf-example.toml to custom.toml and replace its placeholders.
Set the projects/topic, Kafka connection and consumer group, Handle service and
credentials, and output directory. Packaged defaults supply SASL_SSL and PLAIN
for authenticated ESGF Kafka; the example supplies Kafka credential placeholders. Match
these values to your broker; they are connection requirements, not advanced
tuning. See etc/esgf-example.toml for alternative mechanisms and a custom CA.
Ansible uses the same custom.toml for production and installs it as
/etc/piddi/piddi.toml, adding production output/log/database path defaults
only where the TOML omits them. Explicit TOML values take precedence.
The optional deploy/ansible/custom.yml contains only deployment controls;
Kafka, Handle, project, and mapping values belong in TOML once.
See deployment and migration.
You do not need to copy the full packaged defaults. Leave retry delays, monitoring
intervals, mapping limits, and optional backends inherited until you need to tune them.
The packaged default.toml is the full reference, not a setup checklist.
piddi config validate
piddi config explain --project cmip6
piddi config explain --project cmip6 --handle-profile production
explain shows the resolved Handle service, prefix, STAC collection, and lookup
settings, with the configuration keys and files supplying them. It lists loaded
files in precedence order, listing full filenames once with short labels such
as defaults and custom.toml. Settings use those labels; repeated filenames
receive numbered labels to keep their origins distinct. It resolves output,
log, and database paths against
the current working directory. --log is reflected as a command-line override;
terminal logging and disabled database reporting are identified. Username/password
fields are omitted. The installed production config is attributed to
/etc/piddi/piddi.toml; inspect the source custom.toml separately when needed.
Use config show for the merged configuration, or narrow it with
config show --section consumer. Recognized credential fields (including
usernames, passwords, tokens, API keys, and private keys) display as
*** by default, including nested plugin settings. Embedded URL
credentials and recognized secret query parameters are also redacted.
This applies to TOML/JSON output and to section/key filters. Runtime settings
are unchanged. Custom extension secrets should use descriptive credential keys
so they can be recognized.
To explicitly include the original credential values:
piddi config show --show-secrets
piddi config show --format json --show-secrets
config validate runs offline. It checks credentials when SASL PLAIN is selected,
nonnegative retry counts and backoff delays, ordered backoff bounds, and positive
monitoring intervals. Zero retries/delays and zero sample retention (no pruning)
remain supported. Likely misspelled application keys produce suggestions;
arbitrary Kafka options and plugin extensions remain accepted. Demo credential
and missing landing-page warnings concern only configured projects and the
Handle profiles they select (projects = "all" includes all registered projects).
These checks do not test broker connectivity or credential validity.
config show, config explain, and config validate do not initialize file
logging or create log files. They work even if the configured production log
directory is not writable. --log is shown as an override by explain but does
not open the file during inspection.
Routine operation
Plain piddi consume prepares JSONL files. Use piddi consume --publish for
immediate delivery or piddi publish for deferred delivery. Publication mode is
a command choice rather than another site configuration setting.
Select projects with [consumer].projects, repeated --project flags, or
--all-projects. Command-line selection takes precedence. Processes filtering
different projects from the same topic must use different Kafka group.id values.
Use -v for INFO logging, -vv for DEBUG, and --log PATH to select a log file.
For permanent changes, set [logging].level and [logging].file.
Direct rest and pyhandle publication always appends the prepared record to
the project-scoped Handle JSONL file before contacting the service. This audit
output is not optional; [consumer].output_dir controls its root directory.
piddi publish always uses the REST Handle client, independently of the
profile's configured backend. The deferred command
publishes closed daily files using the project's selected profile and its
server_url, prefix, username, password, TLS verification, and timeout
settings. A deferred batch containing multiple projects is rejected; publish
each project's JSONL separately so server selection is unambiguous.
Publication logs
Every successful publication writes an INFO entry to the configured log file
(pid.log by default). Pass -v to enable INFO logging and --log PATH to
override the configured destination. The entry identifies whether the server
created or updated the Handle and includes its directly resolvable REST URL, project,
dataset ID, file name, and source position. For file assets, the publisher joins
IS_PART_OF to a dataset record in the selected batch so the asset log entry
also includes DATASET_ID. Context that is unavailable in older JSONL input is
written as -.
Multiple Handle servers
Each named profile inherits [handles.defaults] and overrides those values
with its own table. All projects inherit [handles].default. A project may select another named
profile with plugins.<name>.handle, and --handle-profile NAME temporarily
overrides both settings for consume, map, publish, or retry. Existing
Handle files retain their mapped prefix, so publication still rejects an
override whose prefix does not match the records.
Plugins can share a service and credentials while using different prefixes:
[handles]
default = "production"
[handles.profiles.production]
server_url = "https://handles.example.org"
prefix = "21.DEFAULT"
username = "shared-user"
password = "replace-me"
[plugins.cmip6]
handle_prefix = "21.CMIP6"
[plugins.cmip7]
handle_prefix = "21.CMIP7"
Both plugins inherit the production profile. A plugin can still select another
service with handle = "another-profile". Prefix precedence is the plugin's
handle_prefix, then the selected profile's prefix, then
[handles.defaults].prefix. Profiles must still provide a fallback prefix,
either directly or through defaults, for callers without a project override.
The plugin prefix also applies when --handle-profile selects a different
service. Mapping,
JSONL output, immediate publication, and deferred publication all use this
effective prefix. The shared credentials must have permission to write each
plugin's prefix.
Keep real credentials in an ignored local override. Configuration examples can
live under etc/.
How inheritance works
Suppose the site file contains the production profile above, and your local
file contains only:
[plugins.cmip6]
handle_prefix = "21.LOCAL"
For CMIP6, the service and credentials still come from handles.profiles.production,
the prefix becomes 21.LOCAL, and the timeout remains inherited from
handles.defaults (10 seconds unless overridden). CMIP7 keeps its own prefix.
piddi config explain --project cmip6 displays these resolved choices.
File merging happens first: packaged defaults → site file → local/--config file.
Project resolution happens afterwards: shared settings → selected profile or
project settings. A local file need only contain the individual keys you change.
Kafka and project STAC settings
Kafka authentication defaults to SASL_SSL with the PLAIN mechanism.
Set broker addresses and credentials in your site/local override. Other
protocols and mechanisms can still be selected there.
The Docker test cluster uses unauthenticated Kafka. Its tests/config.toml
explicitly overrides the protocol, so run it with
piddi --config tests/config.toml consume. For another local configuration, add:
[kafka]
"security.protocol" = "PLAINTEXT"
Omitting this key inherits SASL_SSL; it does not select plaintext automatically.
All additional keys under [kafka] are passed to confluent-kafka. Dotted
librdkafka keys must be quoted in TOML, for example
"bootstrap.servers" = "broker:9092".
Use etc/esgf-example.toml as a starting point for authenticated ESGF Kafka
settings.
Select projects in configuration:
[consumer]
projects = ["cmip6"]
# projects = ["cmip6", "cmip7"]
# projects = "all"
STAC settings may be shared while each project selects its own collection:
[stac]
base_url = "https://discovery.east.esgf.io"
timeout = 10
[plugins.cmip6.stac]
collection = "CMIP6"
[plugins.cmip7.stac]
collection = "CMIP7"
Project settings inherit unspecified values from [stac]. A project-specific
base_url or timeout can therefore be added later if that collection moves to
another service. PATCH events continue to use their own collection_id; the
configured collection is used by STAC version lookups.
Settings reference
All existing settings remain supported. Only override values your site needs.
Site connections and project selection
| Section | Key | Purpose |
|---|---|---|
consumer |
projects |
Plugin names to run, as a list or the string all. |
consumer |
topic |
Kafka topic to consume. |
consumer |
output_dir |
Root for global dump/recovery files and <plugin>/handles/ JSONL output. |
consumer |
max_errors |
Stop after this many processing errors; -1 disables the limit. |
handles |
default |
Handle profile used when a project does not select one explicitly. |
handles.defaults |
backend, verify_https, timeout |
Common values inherited by every named Handle profile. |
handles.profiles.<name> |
backend |
rest for publication or legacy pyhandle; both always write JSONL first. |
handles.profiles.<name> |
server_url, prefix, username, password |
Connection and credentials for one Handle service. |
handles.profiles.<name> |
verify_https, timeout |
TLS verification and per-request timeout for one Handle service. |
stac |
base_url, timeout, collection |
Global STAC defaults; the shared endpoint is https://discovery.east.esgf.io. |
logging |
level |
Baseline DEBUG, INFO, WARNING, ERROR, or CRITICAL level. WARN is accepted as an alias. |
logging |
file |
Log destination. An empty string selects terminal logging. |
Mapping and validation
| Section | Key | Purpose |
|---|---|---|
schema |
strict_mode |
Reject incomplete or unsupported records; defaults to true. |
plugins.<name> |
handle |
Named Handle profile used by this project. |
plugins.<name> |
handle_prefix |
Optional prefix overriding the selected Handle profile's prefix for this project. |
plugins.<name> |
force_dataset_pid |
Default false. Generate dataset PIDs from the full STAC item ID, ignoring source dataset PIDs; also updates file parent links. File tracking IDs are preserved. |
plugins.<name> |
landing_page_url, max_parts, excluded_asset_keys |
Project-specific Handle-record behavior. |
plugins.<name>.stac |
base_url, timeout, collection |
Optional project overrides for the global STAC settings. |
To correct publisher dataset PIDs generated from an unversioned dataset_id,
enable the override only for affected projects in your configuration:
[plugins.cmip7]
force_dataset_pid = true
This applies to mapping, consumption, and retries. Piddi uses its deterministic
UUIDv3 generator with the complete STAC item id (the versioned instance_id).
Source dataset PID fields are ignored, including conflicting compatibility fields.
File IS_PART_OF links point to the generated dataset PID, while file tracking
IDs and dataset HAS_PARTS links retain their existing behavior. The input STAC
JSON is not modified. This does not create redirects for previously published
PIDs; existing mapped Handle JSONL must be regenerated to use the new policy.
The CLI --force option remains separate and controls transient failure handling.
Advanced tuning and optional services
| Section | Key | Purpose |
|---|---|---|
consumer.transient |
stop_on_skip |
Stop after a transient external failure unless --force is used. |
consumer.transient |
retries |
Number of retries for transient STAC patch retrieval. |
consumer.transient |
backoff_initial, backoff_max |
Exponential retry delay bounds in seconds. |
consumer.transient |
preflight_stac |
Probe the configured STAC service before consuming; disabled by default. |
lookup |
enabled, backend |
Enable version lookup using stac or es; disabled by default. |
elasticsearch |
base_url, index |
Elasticsearch lookup settings when lookup.backend = "es". |
stats |
interval_seconds, summary_interval |
Statistics reporting intervals. |
stats |
enable_db, db_path, heartbeat/sample/history intervals |
Local SQLite state and history for piddi consume and piddi map. |
Compatibility with older configuration
Legacy [handle] remains supported and takes precedence over named profiles,
including an explicit --handle-profile selection. A project handle_prefix
still overrides its prefix. Prefer [handles.profiles.<name>] for new setups.
Legacy top-level project tables such as [cmip6] also remain supported. Their
keys override [plugins.cmip6]; nested values such as stac are replaced at
that level rather than recursively merged by project resolution. Prefer
[plugins.<name>] for new setups and avoid mixing both forms.