20260914 强制 TOML 配置并完善 TA 刷新与 daemon
This commit is contained in:
@@ -1,140 +1,127 @@
|
||||
# Command-line reference
|
||||
|
||||
This reference covers v0.1.0. `panda-rpki --help` displays version and usage;
|
||||
there is no separate `--version` option.
|
||||
For every field, default, constraint and complete example, see the [TOML configuration reference](configuration.md)。
|
||||
|
||||
## Syntax
|
||||
Runtime settings come from one explicit TOML file; the binary does not read `PANDA_RPKI_LOG_*` overrides and
|
||||
does not accept legacy validation flags.
|
||||
|
||||
## Commands
|
||||
|
||||
```text
|
||||
panda-rpki validate --tal FILE --ta FILE --out DIRECTORY [OPTIONS]
|
||||
panda-rpki daemon --state-root DIRECTORY [DAEMON OPTIONS] -- [VALIDATION OPTIONS]
|
||||
panda-rpki --help
|
||||
panda-rpki --version
|
||||
panda-rpki -V
|
||||
panda-rpki validate --help
|
||||
panda-rpki daemon --help
|
||||
panda-rpki validate --config FILE
|
||||
panda-rpki validate --config FILE --check-config
|
||||
panda-rpki validate --config FILE --print-config
|
||||
panda-rpki daemon --config FILE
|
||||
panda-rpki daemon --config FILE --check-config
|
||||
panda-rpki daemon --config FILE --print-config
|
||||
```
|
||||
|
||||
Use `--name value`, not `--name=value`. Only help has a short alias (`-h`).
|
||||
Values are case-sensitive; options cannot repeat unless listed as repeatable.
|
||||
Paths are relative to the process working directory. No configuration-file
|
||||
option is provided. No arguments or a help request exits successfully.
|
||||
Only these long options are accepted: `--help`, `--version`, `--config`,
|
||||
`--check-config` and `--print-config`. `-h` aliases help and `-V` aliases
|
||||
version. `--config FILE` is required for a normal validate/daemon run and may
|
||||
also be written as `--config=FILE`. Help does not read a config. Check and print
|
||||
are mutually exclusive and do not run validation. Unknown, repeated or legacy
|
||||
options—including a daemon `--` tail—return exit code 2.
|
||||
|
||||
## Inputs and outputs
|
||||
## TOML schema
|
||||
|
||||
| Option | Default / requirement | Repeatable | Meaning |
|
||||
| --- | --- | --- | --- |
|
||||
| `--tal <file>` | Required | Yes | Local TAL file. |
|
||||
| `--ta <file>` | Required | Yes | Matching DER trust-anchor certificate. |
|
||||
| `--tal-id <id>` | TAL filename stem | Yes | Anchor identifier; if supplied, provide one for every TAL. |
|
||||
| `--ta-constraints <tal-id>=<file>` | Adjacent `.constraints` if present | Yes | Override constraints for a known TAL ID; each ID may occur once. |
|
||||
| `--out <directory>` | Required | No | Output directory, created if absent. Existing output files may be overwritten. |
|
||||
| `--ccr-out <file>` | Disabled | No | CCR DER path, relative to the working directory, not `--out`. |
|
||||
Every file contains `config-version = 1` and a matching `mode` value:
|
||||
|
||||
TAL and TA lists are paired by occurrence order and must have equal lengths.
|
||||
Use distinct TAL IDs. For `input/anchor.tal`, automatic discovery checks
|
||||
`input/anchor.constraints`. If absent with no explicit path, no additional
|
||||
constraints are loaded for that anchor.
|
||||
```toml
|
||||
config-version = 1
|
||||
mode = "validate"
|
||||
out = "output"
|
||||
rrdp-state-dir = "state"
|
||||
rrdp-sync-mode = "auto"
|
||||
ccr-out = "output/result.ccr"
|
||||
publish-dir = "publish"
|
||||
ta-refresh-policy = "allow-valid-cache"
|
||||
require-complete = false
|
||||
|
||||
## State and network
|
||||
[[anchors]]
|
||||
id = "ripe"
|
||||
tal = "input/ripe.tal"
|
||||
ta = "input/ripe.cer" # omit for automatic refresh from the TAL URI
|
||||
constraints = "input/ripe.constraints"
|
||||
```
|
||||
|
||||
| Option | Default | Meaning |
|
||||
| --- | --- | --- |
|
||||
| `--rrdp-state-dir <directory>` | `<out>/.state` | Dedicated persistent root; database is stored in `repository-db/`. |
|
||||
| `--rrdp-sync-mode <auto\|snapshot\|delta>` | `auto` | Starting state requirements described below. |
|
||||
| `--http-timeout-secs <n>` | `300` | HTTP timeout seconds; nonnegative with runtime minimum 1. Connection, retry and large-object transport policies also apply. Not a whole-run deadline. |
|
||||
| `--http-root-cert <pem>` | None | Repeatable extra HTTPS roots; system roots and hostname verification remain enabled. |
|
||||
| `--max-ca-depth <n>` | `64` | Nonnegative CA traversal depth limit. |
|
||||
All paths are relative to the TOML file, not the process working directory.
|
||||
Absolute paths are accepted. `id` defaults to the TAL filename stem and must be
|
||||
unique. `constraints` defaults to a same-stem `.constraints` file beside the
|
||||
TAL. Automatic TA refresh supports HTTPS and rsync, validates the TAL binding,
|
||||
signature and current validity, and stores a keyed cache at
|
||||
`<rrdp-state-dir>.ta-cache/`. `allow-valid-cache` may use a still-valid cached
|
||||
certificate when refresh fails and marks the run partial; `require-fresh` does
|
||||
not fall back.
|
||||
|
||||
| Mode | Starting state | Behavior |
|
||||
| --- | --- | --- |
|
||||
| `auto` | Empty or populated database | Select snapshot, delta or noop per repository. |
|
||||
| `snapshot` | Missing or empty database | Start fresh; reject a populated database. |
|
||||
| `delta` | Existing populated database | Resume state, allowing protocol snapshot fallback and new-repository snapshots. |
|
||||
The remaining common keys and defaults are:
|
||||
|
||||
Unrecognized state layouts and unsupported database schemas are rejected.
|
||||
Use a new dedicated directory for an incompatible format. State includes
|
||||
repository objects, RRDP sessions and manifest anti-rollback metadata. Do not
|
||||
share a writable database between processes. Changing `--out` changes default
|
||||
state location unless `--rrdp-state-dir` is explicit.
|
||||
| Key | Default |
|
||||
| --- | ---: |
|
||||
| `max-ca-depth` | 64 |
|
||||
| `http-timeout-secs` | 300 (0 is normalized to 1) |
|
||||
| `http-root-cert` | `[]` |
|
||||
| `parallel-max-repo-sync-workers-global` | 8 |
|
||||
| `parallel-phase2-object-workers` | 8 |
|
||||
| `parallel-phase2-worker-queue-capacity` | 256 |
|
||||
| `parallel-repo-worker-queue-capacity` | 256 (effective minimum 1024) |
|
||||
| `log-level` | `info` |
|
||||
| `log-format` | `text` |
|
||||
| `log-progress-interval-secs` | 10 |
|
||||
| `run-timeout-secs` | 0 (disabled) |
|
||||
| `require-complete` | `false` |
|
||||
|
||||
RRDP references and redirects enforce HTTPS and same-origin rules. Extra
|
||||
trust roots do not relax origin checks. No separate rsync timeout is exposed.
|
||||
Validate-only keys are `out` (required), `rrdp-state-dir`, `rrdp-sync-mode`,
|
||||
`ccr-out` and optional `publish-dir`. Daemon-only keys are `state-root`
|
||||
(required), `interval-secs` (60), `max-runs` (unlimited), `retain-runs` (10)
|
||||
and `shutdown-grace-secs` (30). Daemon does not accept validate-only keys; it
|
||||
creates a per-run validate TOML internally.
|
||||
|
||||
## Workers and queues
|
||||
## Inspection and outcomes
|
||||
|
||||
| Option | Default | Meaning |
|
||||
| --- | ---: | --- |
|
||||
| `--parallel-max-repo-sync-workers-global <n>` | 8 | Global repository transport workers. |
|
||||
| `--parallel-phase2-object-workers <n>` | 8 | Object workers, independent of transport. |
|
||||
| `--parallel-phase2-worker-queue-capacity <n>` | 256 | Object-worker queue capacity. |
|
||||
| `--parallel-repo-worker-queue-capacity <n>` | 256 | Pending repository results; effective limit is `max(n, 1024)`. |
|
||||
`--check-config` validates syntax, fields, local TAL/TA/constraints and existing
|
||||
path types without network access, directory creation, state writes or locks.
|
||||
`--print-config` emits `configVersion`, `mode`, `effective`, `sources` and
|
||||
`normalizations` as JSON; defaults are filled and paths are absolute.
|
||||
|
||||
All values must be positive. Budgets are shared across TALs. Higher concurrency
|
||||
can increase memory consumption and does not guarantee proportional speedup.
|
||||
Validation writes `summary.json`, `vrps.csv`, `vaps.csv`, timing files and an
|
||||
optional CCR. The final `result-complete.json` is written only after all required
|
||||
artifacts are ready. `resultStatus` is `success`, `partial` or `failed`:
|
||||
|
||||
## Logging
|
||||
| Status | Default exit | `require-complete = true` |
|
||||
| --- | ---: | ---: |
|
||||
| success | 0 | 0 |
|
||||
| partial | 0 | 3 |
|
||||
| failed | 2 | 2 |
|
||||
|
||||
| Option | Default | Values |
|
||||
| --- | --- | --- |
|
||||
| `--log-level <level>` | `info` | `off`, `error`, `warn`, `info`, `debug`, `trace` |
|
||||
| `--log-progress-interval-secs <seconds>` | `10` | Periodic progress; `0` disables periodic events, not stage events. CLI overrides `PANDA_RPKI_LOG_PROGRESS_INTERVAL_SECS`. |
|
||||
| `--log-format <format>` | `text` | `text`, `json` |
|
||||
`summary.json` adds `trustAnchors`, `taFailedCount`,
|
||||
`repositoryFailedCount`, `taCacheFallbackCount`, `resultStatus` and
|
||||
`publicationStatus`. A cache fallback or a failed anchor makes an otherwise
|
||||
complete artifact set partial; rejected objects alone do not.
|
||||
|
||||
Precedence: explicit option, then `PANDA_RPKI_LOG_LEVEL` or
|
||||
`PANDA_RPKI_LOG_FORMAT`, then default. Each level includes more severe messages.
|
||||
`off` suppresses logs but does not change exit codes. JSON logs contain
|
||||
`timestamp`, `level`, `event`, and `fields`, one object per line. Logs use stderr;
|
||||
help uses stdout; validation results are written to files.
|
||||
With `publish-dir`, only a complete success is copied to an immutable run:
|
||||
|
||||
Other `PANDA_RPKI_*` variables in [Compose](docker.md) are template substitutions,
|
||||
not configuration variables read directly by the binary.
|
||||
```text
|
||||
publish/runs/<run-id>/{vrps.csv,vaps.csv,summary.json,stage-timing.json,
|
||||
analysis/timing.json,result-complete.json[,result.ccr]}
|
||||
publish/latest -> runs/<run-id>
|
||||
publish/last-attempt.json
|
||||
```
|
||||
|
||||
## Daemon
|
||||
`latest` changes atomically and never moves for partial or failed attempts.
|
||||
Daemon uses its existing `state-root/runs/run_000001/` layout and atomically
|
||||
points `state-root/latest` at the newest successful run; it retains completed
|
||||
runs according to `retain-runs` while preserving the latest pointer.
|
||||
|
||||
Daemon runs in the foreground, launching this executable's `validate` command
|
||||
in a separate process per cycle. Pass validator options after `--`, without
|
||||
the word `validate`. The controller owns `--out`, `--ccr-out`,
|
||||
`--rrdp-state-dir` and `--rrdp-sync-mode`; do not pass them after `--`.
|
||||
## Configuration lifecycle
|
||||
|
||||
| Option | Default | Meaning |
|
||||
| --- | --- | --- |
|
||||
| `--state-root <directory>` | Required | Dedicated root for state, lifecycle metadata and run outputs. |
|
||||
| `--interval-secs <n>` | 60 | Wait after run recording and retention; zero starts the next run immediately. |
|
||||
| `--max-runs <n>` | Unlimited | Positive attempt count for this invocation, including failed attempts. |
|
||||
| `--retain-runs <n>` | 10 | Positive number of completed run directories retained, including recorded failures. Older completed directories are deleted. |
|
||||
| `--run-timeout-secs <n>` | 0 | Whole-run deadline; zero disables. Sends SIGTERM to the child group, then SIGKILL after two seconds if needed. |
|
||||
| `--shutdown-grace-secs <n>` | 30 | On SIGINT/SIGTERM, stop starting runs and wait at most n seconds before terminating the active process group. |
|
||||
|
||||
Options cannot repeat. Seconds are nonnegative. Empty state starts with
|
||||
snapshot, successful continuation requests delta, and recovery after a failed
|
||||
run with existing state requests auto. Actual operations can include noop and
|
||||
snapshot fallback. Normal child failures/timeouts are recorded and retried;
|
||||
corrupt lifecycle metadata or inability to record state stops the controller.
|
||||
|
||||
Restart continues numbering and reuses state. Retention leaves incomplete,
|
||||
unrelated and symlink run directories untouched. It does not trim history JSONL.
|
||||
Do not remove a live lock file. After SIGKILL, ensure the old validator child
|
||||
has stopped before restarting. Stop the entire container for Docker deployments.
|
||||
|
||||
## Outputs and exit status
|
||||
|
||||
| File | Content |
|
||||
| --- | --- |
|
||||
| `summary.json` | TAL, worker, validation and actual RRDP operation counts. |
|
||||
| `vrps.csv` | ROA payloads: `asn,prefix,max_length`. |
|
||||
| `vaps.csv` | ASPA payloads. |
|
||||
| `stage-timing.json`, `analysis/timing.json` | Timing and analysis counters. |
|
||||
| `.vrps-source.csv` | Intermediate CSV used to produce `vrps.csv`. |
|
||||
| Requested CCR path | Optional CCR DER; automatic per run in daemon mode. |
|
||||
|
||||
Daemon adds `daemon.lock`, `daemon-status.json`, `lifecycle.json`,
|
||||
`run-summary.jsonl`, `state/repository-db/`, and `runs/run_000001/` etc.
|
||||
Each run includes validator outputs, `run-meta.json`, `run-summary.json`,
|
||||
`process-output.txt`, `validator.log` and optional `process-time.txt`. `/usr/bin/time`
|
||||
provides user/system CPU and peak RSS when installed; Docker includes it.
|
||||
Controller states: `starting`, `running`, `sleeping`, `exited`, `failed`.
|
||||
|
||||
Help and successful validation return 0; argument and propagated runtime
|
||||
errors return 2. Completion can include rejected objects or recoverable
|
||||
repository failures: inspect warnings and outputs too. Failed runs can leave
|
||||
partial output; use a separate output directory per cycle.
|
||||
|
||||
A bounded daemon returns 2 if any attempt failed, otherwise 0. Stopping during
|
||||
an interval exits normally. A forcibly terminated current run is recorded as
|
||||
failed and causes exit 2.
|
||||
TAL files are never auto-updated. Omitting an anchor's `ta` field refreshes its
|
||||
TA certificate on each cycle; providing `ta` selects fixed mode. TOML is read
|
||||
once at process start. Put `log-format = "text"` and `ta-refresh-policy` at the
|
||||
top level, before any `[[anchors]]` tables. See [Docker reload steps](docker.md#graceful-stop-edit-and-reload)
|
||||
and [complete container TOML examples](../docker/examples/README.md).
|
||||
|
||||
294
docs/configuration.md
Normal file
294
docs/configuration.md
Normal file
@@ -0,0 +1,294 @@
|
||||
# Complete TOML configuration reference (schema v1)
|
||||
|
||||
This reference documents all 26 top-level settings and four anchor fields. The product provides validation and a daemon
|
||||
that schedules validation cycles. SLURM, RTR, ROV, HTTP/API services, offline
|
||||
validation and additional payload JSON export are outside this configuration.
|
||||
|
||||
## 1. Loading a configuration
|
||||
|
||||
```bash
|
||||
panda-rpki validate --config /srv/panda/validate.toml --check-config
|
||||
panda-rpki validate --config /srv/panda/validate.toml --print-config
|
||||
panda-rpki validate --config /srv/panda/validate.toml
|
||||
```
|
||||
|
||||
Use `daemon` and a daemon configuration for continuous operation. Normal runs,
|
||||
checks and printing all require one explicit file. Check and print are mutually
|
||||
exclusive. There is no default-file discovery, include, profile merging, or
|
||||
business-setting override. Old `--tal`, `--ta`, `--out`, `--log-format` options
|
||||
and daemon `--` forwarding are rejected. `PANDA_RPKI_LOG_*` does not override
|
||||
TOML. Standard dependency environments such as proxy settings are separate from
|
||||
this application configuration contract.
|
||||
|
||||
Settings come from TOML, then built-in defaults. Unknown keys, duplicate TOML
|
||||
keys, incorrect types and a mismatched mode return exit code 2. Quote strings,
|
||||
leave integers unquoted, use `true`/`false` for booleans, and use `[]` for an empty
|
||||
array. TOML has no null value: omit optional paths rather than writing `null`,
|
||||
an empty path, or an empty string.
|
||||
|
||||
Write all top-level settings before the first `[[anchors]]` table. Fields after
|
||||
that header belong to the current anchor until another table header appears.
|
||||
For example, putting `log-format` after `tal` makes it an unknown anchor field.
|
||||
|
||||
```toml
|
||||
config-version = 1
|
||||
mode = "validate"
|
||||
out = "output"
|
||||
log-format = "text" # Top-level setting: keep this before [[anchors]].
|
||||
|
||||
[[anchors]]
|
||||
id = "ripe"
|
||||
tal = "input/ripe.tal"
|
||||
```
|
||||
|
||||
## 2. Common top-level settings
|
||||
|
||||
These settings apply to both commands. Defaults below describe omitted fields.
|
||||
The examples explicitly choose a 1,800-second timeout and strict completion;
|
||||
those choices do not change the built-in defaults.
|
||||
|
||||
| Key | Type | Default / required | Meaning and constraints |
|
||||
| --- | --- | --- | --- |
|
||||
| `config-version` | Integer | Explicit `1` required | Configuration schema version, not the software version. Missing or unsupported versions are rejected. |
|
||||
| `mode` | String | Required | `validate` or `daemon`; must match the command. |
|
||||
| `anchors` | Array of tables | At least one required | Write `[[anchors]]` entries; see section 5. No automatic TAL-directory scan. |
|
||||
| `ta-refresh-policy` | String | `allow-valid-cache` | On automatic TA download failure, permit a revalidated, usable cached certificate. `require-fresh` prohibits fallback. Does not replace fixed TA files. |
|
||||
| `max-ca-depth` | Nonnegative integer | 64 | Maximum CA validation-tree depth. Zero is accepted by configuration parsing, but is a depth limit, not unlimited traversal. Usually keep 64. |
|
||||
| `http-timeout-secs` | Nonnegative integer, seconds | 300 | HTTP fetch timeout. Zero is normalized to one second, not unlimited. Does not set the whole-run or rsync timeout. |
|
||||
| `http-root-cert` | Array of path strings | `[]` | Additional HTTP TLS root certificates in PEM format. Every file must be readable and parseable. Empty means no custom additions; system TLS trust remains. These are not RPKI TA certificates. |
|
||||
| `parallel-max-repo-sync-workers-global` | Positive integer | 8 | Global repository-sync worker count. Zero is rejected. |
|
||||
| `parallel-phase2-object-workers` | Positive integer | 8 | Phase-2 object-processing worker count. Zero is rejected. |
|
||||
| `parallel-phase2-worker-queue-capacity` | Positive integer | 256 | Phase-2 worker queue capacity. Zero is rejected. |
|
||||
| `parallel-repo-worker-queue-capacity` | Positive integer | Input default 256; effective 1024 | Repository worker queue capacity. Zero is rejected; values 1–1023 are raised to 1024. Print-config reports normalization. |
|
||||
| `log-level` | String | `info` | `off`, `error`, `warn`, `info`, `debug`, or `trace`; case-sensitive. |
|
||||
| `log-format` | String | `text` | Human-readable English diagnostics or `json` events, one object per line. Does not change summary or metadata formats. |
|
||||
| `log-progress-interval-secs` | Nonnegative integer, seconds | 10 | Periodic progress interval. Zero disables periodic progress, not other stage messages. Levels off/error/warn do not start a progress thread. |
|
||||
| `require-complete` | Boolean | false | A partial run exits 0 when false, 3 when true. Does not change validation rules, turn partial into success, or permit partial publication. |
|
||||
| `run-timeout-secs` | Nonnegative integer, seconds | 0 | Whole-run budget; zero disables it. Validate includes runtime TA acquisition and output preparation. Daemon measures from child startup and enforces the budget in the controller. Check/print do not use this budget. |
|
||||
|
||||
Integers are also limited by TOML and the target platform's integer types.
|
||||
Larger worker counts do not guarantee higher throughput; consider CPU, memory
|
||||
and repository-service load.
|
||||
|
||||
## 3. Validate-only settings
|
||||
|
||||
These keys are rejected in daemon configurations, even when set to their usual
|
||||
default values.
|
||||
|
||||
| Key | Type | Default / required | Meaning and constraints |
|
||||
| --- | --- | --- | --- |
|
||||
| `out` | Directory path | Required | Current-attempt output: CSV, summary, timing files and completion marker. A partial run can also produce artifacts. |
|
||||
| `rrdp-state-dir` | Directory path | `<out>/.state` | Persistent protocol state containing repository-db. Reuse for incremental synchronization; runtime access is exclusive. |
|
||||
| `rrdp-sync-mode` | String | `auto` | `auto` selects synchronization according to available state; `snapshot` requires empty state; `delta` requires an existing database. Individual repositories can still use protocol fallback. |
|
||||
| `ccr-out` | File path | Omitted: no CCR | For example, `output/result.ccr`. Can be outside out. An existing target must be a file, not a directory. |
|
||||
| `publish-dir` | Directory path | Omitted: disabled | Immutable successful result copies and latest pointer. Must not equal, contain, or be contained by out or protocol state. Uses additional disk space; Successful copies in publish/runs are not automatically pruned. |
|
||||
|
||||
## 4. Daemon-only settings
|
||||
|
||||
These keys are rejected in validate configurations.
|
||||
|
||||
| Key | Type | Default / required | Meaning and constraints |
|
||||
| --- | --- | --- | --- |
|
||||
| `state-root` | Directory path | Required | Controller root; daemon manages state, runs, locks, status files and latest beneath it. |
|
||||
| `interval-secs` | Nonnegative integer, seconds | 60 | Delay after one cycle finishes before the next starts, not a fixed start-to-start period. Zero runs cycles consecutively. |
|
||||
| `max-runs` | Positive integer | Omitted: unlimited | Maximum cycles in the current process, not the maximum historical sequence number. Zero is rejected. |
|
||||
| `retain-runs` | Positive integer | 10 | Retain the newest N completed runs plus an older run referenced by latest. Not a hard limit on every directory. Zero is rejected. |
|
||||
| `shutdown-grace-secs` | Nonnegative integer, seconds | 30 | Time allowed for the active child to finish after a stop request. Then TERM, followed by KILL after another two seconds. Zero skips waiting for natural completion. Separate from run timeout. |
|
||||
|
||||
Each cycle generates `runs/run_XXXXXX/validator-config.toml` with absolute paths.
|
||||
The controller supplies output, CCR and synchronization settings. The child
|
||||
configuration has run-timeout-secs=0 because the parent enforces the budget.
|
||||
Editing generated child configurations is not a persistent configuration change.
|
||||
|
||||
The controller requests snapshot for empty state, delta after success and auto
|
||||
after partial/failed. Ordinary partial/failed cycles do not prevent subsequent
|
||||
cycles. On finite completion or stop, the aggregate exit is 2 if any cycle failed;
|
||||
otherwise 3 if strict completion is enabled and any cycle was partial; otherwise
|
||||
0. An exited container with code 3 does not imply Docker failed to stop it.
|
||||
|
||||
## 5. Anchor fields
|
||||
|
||||
| Key | Type | Default / required | Meaning and constraints |
|
||||
| --- | --- | --- | --- |
|
||||
| `id` | String | TAL filename stem | Identifier in results, logs and constraints. An explicitly empty string also falls back to the filename stem. Resolved IDs must be nonempty and unique; explicit names are preferred. |
|
||||
| `tal` | File path | Required | TAL obtained from an independently trusted source; must exist and parse during preflight. Contains certificate URIs and the trusted public key. |
|
||||
| `ta` | File path | Omitted: automatic mode | If present, selects a fixed DER TA certificate. Preflight checks binding, certificate profile/signature and validity. Network downloads do not silently replace it. |
|
||||
| `constraints` | File path | Discover same-stem `.constraints` | For ripe.tal, try ripe.constraints. Absence of that file means no additional constraints. An explicit path must exist and parse. Omitting this setting does not disable discovery; an empty string is not a disable switch. |
|
||||
|
||||
Automatic refresh updates the **TA certificate, never the TAL file**. Each
|
||||
validate run or daemon cycle tries the TAL's HTTPS/rsync URIs in order. There is
|
||||
no separate background refresh timer, and no invented HTTPS alternative for an
|
||||
rsync-only TAL. Candidates must pass certificate and TAL-binding validation.
|
||||
|
||||
The cache is `<rrdp-state-dir>.ta-cache`, keyed by the TAL public-key SHA-256.
|
||||
Download failure permits fallback only under allow-valid-cache with a usable,
|
||||
revalidated cached certificate; that makes the result at least partial.
|
||||
Require-fresh prohibits fallback. Existing fixed `.cer` files do not seed this
|
||||
cache automatically; switching to automatic mode initially needs reachable URIs.
|
||||
One failed TA with others completing yields partial; all TAs failing yields
|
||||
failed. A fixed-certificate error found during preflight exits 2 immediately.
|
||||
|
||||
## 6. Paths, mounts, reload and concurrency
|
||||
|
||||
- `--config FILE` is relative to the process working directory. Paths inside
|
||||
TOML are relative to the resolved configuration file location; existing
|
||||
symlink ancestors are resolved. Absolute paths are accepted. There is no `~`,
|
||||
`$HOME` or `${VAR}` expansion inside TOML strings.
|
||||
- Moving a configuration can change every relative path. Keep temporary profile
|
||||
copies in the same directory; concurrent instances additionally need separate
|
||||
output, state and publication roots.
|
||||
- Docker TOML uses container paths; Compose CONFIG_FILE/INPUT_DIR/STATE_DIR
|
||||
variables use host paths. Those variables select mounts/image/UID, not
|
||||
application settings.
|
||||
- The TA cache is a sibling of protocol state. With a writable /state mount,
|
||||
use `rrdp-state-dir="/state/repository"` so repository and repository.ta-cache
|
||||
are both writable and persistent. Using /state directly places the cache at
|
||||
/state.ta-cache, which needs a separate mount. Plan stopped migration for
|
||||
existing databases; changing a path does not migrate the old database.
|
||||
- Daemon's /data/state and /data/state.ta-cache already share the /data mount.
|
||||
- TOML is loaded once at process startup. Daemon rereads the configured TAL/TA/
|
||||
constraints files each cycle. TOML changes require a process restart. If an
|
||||
editor or sed -i replaces a single-file bind mount's host inode, recreate the
|
||||
container so the new file is mounted.
|
||||
- Runtime locks protect output, state and publication roots. Preflight does not
|
||||
acquire runtime locks. Passing it does not prove future write permissions,
|
||||
network access, free space or exclusive access.
|
||||
|
||||
See [Docker operations](docker.md#graceful-stop-edit-and-reload) for complete
|
||||
stop, check and recreate commands.
|
||||
|
||||
## 7. Results and consistent reads
|
||||
|
||||
| Status | Conditions in brief | Default exit | Strict exit | Update latest |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| success | All configured TAs complete, no terminal repository failures or cache degradation, required artifacts complete | 0 | 0 | Yes |
|
||||
| partial | Some TA/repository terminal failure or valid TA-cache fallback, with usable completed results | 0 | 3 | No |
|
||||
| failed | Configuration/lock/fatal failure, all TAs fail, timeout, interruption, output or publication failure | 2 | 2 | No |
|
||||
|
||||
Rejecting invalid objects according to the standards does not itself imply
|
||||
partial. A recoverable RRDP failure followed by valid fallback need not imply
|
||||
partial either. Read resultStatus and the typed repositoryFailedCount rather
|
||||
than inferring status from warning counts.
|
||||
|
||||
Out contains the current attempt. Atomic replacement of individual files is
|
||||
not an atomic multi-file snapshot. The result-complete.json marker is written
|
||||
last; a partial attempt can have a marker and still be partial. Only success is
|
||||
copied to publish/runs/<id> and switches latest. Resolve latest once, then read
|
||||
all files from that immutable directory. Daemon uses its existing run directory
|
||||
without a second publication copy. Latest is absent before the first success;
|
||||
upgrading an existing state root does not create latest from historical runs;
|
||||
the pointer is established by the first subsequent complete success.
|
||||
|
||||
Text logging affects diagnostics only: summary, completion markers and printed
|
||||
configuration remain JSON. Daemon lifecycle diagnostics are in container logs;
|
||||
child validation diagnostics are in that run's validator.log. Historical logs
|
||||
are not converted.
|
||||
|
||||
## 8. Complete examples and selection
|
||||
|
||||
The [native configuration directory](../examples/config/README.md) contains
|
||||
copyable files:
|
||||
|
||||
| File | Scenario | Explicit choices |
|
||||
| --- | --- | --- |
|
||||
| validate-minimal.toml | Minimal single automatic TA | Required fields only; built-in defaults otherwise |
|
||||
| validate-full.toml | All common/validate settings and successful publication | Text logs, strict completion, 1,800-second budget |
|
||||
| validate-fixed.toml | Fixed certificate | Both tal and ta; certificate must match and be valid |
|
||||
| daemon-all5.toml | Continuous five-TA automatic refresh | All common/daemon settings; max-runs omitted |
|
||||
| daemon-three.toml | Three five-TA cycles | max-runs=3, interval=0, independent state root |
|
||||
|
||||
For containers, use the [four Docker configurations](../docker/examples/README.md).
|
||||
Mounting a native relative-path example under /config does not automatically
|
||||
make its paths correct.
|
||||
|
||||
### 8.1 Minimal complete validate configuration
|
||||
|
||||
Save as /srv/panda/validate.toml and prepare /srv/panda/input/ripe.tal:
|
||||
|
||||
```toml
|
||||
config-version = 1
|
||||
mode = "validate"
|
||||
out = "output"
|
||||
|
||||
[[anchors]]
|
||||
id = "ripe"
|
||||
tal = "input/ripe.tal"
|
||||
```
|
||||
|
||||
Run `panda-rpki validate --config /srv/panda/validate.toml`. Default state is
|
||||
/srv/panda/output/.state; the TA cache is /srv/panda/output/.state.ta-cache.
|
||||
Defaults are text/info, no CCR, no publication root and no whole-run timeout.
|
||||
Partial also exits 0 by default. Add require-complete=true at the top level for
|
||||
strict completion.
|
||||
|
||||
### 8.2 Fixed, automatic and mixed anchors: replacement fragment
|
||||
|
||||
```toml
|
||||
[[anchors]]
|
||||
id = "ripe"
|
||||
tal = "input/ripe.tal"
|
||||
ta = "input/ripe.cer" # Fixed; remove this key to switch to automatic.
|
||||
|
||||
[[anchors]]
|
||||
id = "apnic"
|
||||
tal = "input/apnic.tal" # Automatic.
|
||||
```
|
||||
|
||||
This replaces the anchors section of a complete configuration; it is not a
|
||||
standalone file. Mixed mode needs no extra mode switch. Changing
|
||||
TA refresh policy does not make an anchor with an explicit ta automatic.
|
||||
|
||||
### 8.3 Logging, TLS and worker tuning: top-level fragment
|
||||
|
||||
```toml
|
||||
log-format = "json"
|
||||
log-level = "debug"
|
||||
log-progress-interval-secs = 0
|
||||
http-timeout-secs = 600
|
||||
http-root-cert = ["tls/internal-root.pem"]
|
||||
parallel-phase2-object-workers = 4
|
||||
parallel-max-repo-sync-workers-global = 4
|
||||
parallel-phase2-worker-queue-capacity = 256
|
||||
parallel-repo-worker-queue-capacity = 1024
|
||||
```
|
||||
|
||||
Replace existing top-level settings; do not add duplicate keys. Prepare the
|
||||
custom TLS PEM file first, or keep [] when no extra roots are needed. This does
|
||||
not change the TAL public key, relax TA validation or disable system TLS checks.
|
||||
|
||||
## 9. Preflight and troubleshooting
|
||||
|
||||
Check first, print effective configuration, then run normally. Check does not
|
||||
use the network, take runtime locks or create run directories. It reads TOML,
|
||||
TALs, fixed TAs, constraints and extra HTTP roots. Print performs the same checks
|
||||
and emits effective settings, sources and normalizations.
|
||||
|
||||
For example, setting http-timeout-secs to 0 and the repository queue to 256
|
||||
produces this excerpt, not the full print output:
|
||||
|
||||
```json
|
||||
{
|
||||
"effective": {
|
||||
"http-timeout-secs": 1,
|
||||
"parallel-repo-worker-queue-capacity": 1024
|
||||
},
|
||||
"normalizations": [
|
||||
{"field":"http-timeout-secs","input":0,"effective":1},
|
||||
{"field":"parallel-repo-worker-queue-capacity","input":256,"effective":1024}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
| Symptom | Explanation and action |
|
||||
| --- | --- |
|
||||
| Missing configuration/version error | Explicitly write config-version=1 and pass --config. |
|
||||
| Mode mismatch | Match the command and mode. |
|
||||
| Unknown anchor field log-format | Move it before the first [[anchors]] table. |
|
||||
| Out is not allowed in daemon | Remove validate-only keys; the controller owns output. |
|
||||
| Zero workers/queues/max-runs/retention | Use positive values; omit max-runs for unlimited cycles. |
|
||||
| File not found | Resolve paths against the config directory; check container mounts. |
|
||||
| No automatic TA cache | First use needs a successful download; fixed cer files do not seed the cache. |
|
||||
| Preflight passes, runtime fails | Check does not test network reachability, runtime locks or actual writes. |
|
||||
| Logs still JSON | Check top-level settings, recreate the container and inspect new logs. Metadata remains JSON intentionally. |
|
||||
| Exited with code 3 | Stopped with partial aggregate results; inspect summaries/lifecycle logs rather than repeatedly stopping. |
|
||||
| Latest absent | No complete success yet; partial does not publish even when it exits 0. |
|
||||
@@ -12,7 +12,7 @@
|
||||
| CMS signed-object profile | RFC 6488 §§2–3; RFC 9589 §4 | `src/model/signed_object.rs` | signed-object profile tests |
|
||||
| RRDP notification, snapshot, delta/replace/withdraw and fallback | RFC 8182 §§3.4–3.5 | `src/repository/sync/rrdp.rs`, `src/repository/sync/repo.rs` | snapshot/delta state-restart unit tests and synthetic Docker tests |
|
||||
| RRDP direct-reference and redirect origin checks | RFC 9674 §3.2 | `src/repository/fetch/http.rs`, `src/repository/sync/rrdp.rs` | cross-origin unit tests |
|
||||
| Repeated TAL/TA pairing and aggregate output | RFC 8630 §2 for each TAL; aggregation is an implementation choice | `src/cli/mod.rs`, `src/cli/validate.rs`, `src/runtime/` | CLI parser checks and multi-TAL integration evidence |
|
||||
| Named TOML anchors with TAL/TA binding and aggregate output | RFC 8630 §2 for each TAL; aggregation is an implementation choice | `src/cli/mod.rs`, `src/cli/validate.rs`, `src/runtime/` | CLI parser checks and multi-TAL integration evidence |
|
||||
| Bounded repository and object workers (default 8 each, shared across TALs) | operational support for the standard validation pipeline | `src/scheduler/`, `src/runtime/` | worker-pool unit tests |
|
||||
| Resumable RRDP protocol state | RFC 8182 §3.4 | `src/repository/storage/`, `src/repository/sync/rrdp.rs` | atomic state index and restart delta test |
|
||||
| CCR manifest, ROA, ASPA, trust-anchor and router-key states | `draft-ietf-sidrops-rpki-ccr-11` §§2–4 | `src/ccr/` | encode/decode tests and integration artifacts |
|
||||
@@ -22,7 +22,8 @@
|
||||
References identify the implemented profiles, not a certification of complete
|
||||
RFC compliance. Draft revisions are intentionally explicit and are not claims
|
||||
of compatibility with later revisions. The CLI uses HTTPS RRDP, requires local
|
||||
TAL/TA pairs, and does not provide RTR or automatic TA-certificate refresh.
|
||||
TALs, supports fixed or automatically refreshed TA certificates, and does not provide RTR.
|
||||
TAL files themselves are not automatically updated.
|
||||
CCR tests establish encoding and payload consistency, not independent
|
||||
revalidation of the entire trust chain by another relying party.
|
||||
|
||||
|
||||
312
docs/docker.md
312
docs/docker.md
@@ -1,199 +1,189 @@
|
||||
# Docker and Compose
|
||||
|
||||
Run commands from the project root. A Linux Docker engine is required for the
|
||||
documented deployment and integration tests.
|
||||
For every field, default, constraint and complete example, see the [TOML configuration reference](configuration.md)。
|
||||
|
||||
The image contains the validator, `rsync`, CA certificates and `/usr/bin/time`.
|
||||
The root filesystem is read-only; input and configuration are read-only; output and
|
||||
state mounts are writable. The application receives a subcommand and one configuration option:
|
||||
`validate|daemon --config FILE`.
|
||||
|
||||
Build the image:
|
||||
|
||||
```bash
|
||||
docker build -f docker/Dockerfile -t panda-rpki:v0.1.0 .
|
||||
```
|
||||
|
||||
The image defaults to an unprivileged user and includes CA certificates,
|
||||
`rsync` and `/usr/bin/time`. Compose uses a read-only root filesystem and a
|
||||
temporary `/tmp`. Host input mounts are read-only; state and outputs are writable.
|
||||
## Single validate run
|
||||
|
||||
## Single anchor
|
||||
Create a TOML whose paths are valid **inside** the container:
|
||||
|
||||
```toml
|
||||
config-version = 1
|
||||
mode = "validate"
|
||||
out = "/output"
|
||||
rrdp-state-dir = "/state/repository"
|
||||
ccr-out = "/output/result.ccr"
|
||||
|
||||
[[anchors]]
|
||||
id = "anchor"
|
||||
tal = "/input/anchor.tal"
|
||||
# ta = "/input/anchor.cer" # uncomment for fixed TA mode
|
||||
```
|
||||
|
||||
Run the provided Compose template:
|
||||
|
||||
```bash
|
||||
mkdir -p state output
|
||||
export CONFIG_FILE="$PWD/validate.toml"
|
||||
export INPUT_DIR="$PWD/input" STATE_DIR="$PWD/state" OUTPUT_DIR="$PWD/output"
|
||||
export TAL_FILE=anchor.tal TA_FILE=anchor.cer
|
||||
export PUID="$(id -u)" PGID="$(id -g)"
|
||||
docker compose -f docker/compose.yaml run --build --rm validator
|
||||
```
|
||||
|
||||
Supply absolute host paths as above. Relative Compose paths are resolved from
|
||||
the Compose file's directory, which is `docker/`. Build context is explicitly
|
||||
the project root. `PANDA_RPKI_RRDP_SYNC_MODE` defaults to `auto`.
|
||||
The template mounts the TOML read-only at `/config/validate.toml` and invokes
|
||||
`panda-rpki validate --config /config/validate.toml`. Host variables only select
|
||||
mounts, image and container UID/GID; they are not read as validator settings.
|
||||
|
||||
## All five regional anchors
|
||||
## All five RIRs
|
||||
|
||||
Follow [Prepare all five RIR trust anchors](trust-anchors.md) to download and
|
||||
check each TAL and matching certificate under `input/`, then run:
|
||||
Put the five RIR TAL files (TA certificates are optional) under `input/` and list them as named anchors in a
|
||||
TOML with `/input/...` paths. Then set `CONFIG_FILE` to that file and run:
|
||||
|
||||
```bash
|
||||
mkdir -p state output
|
||||
export INPUT_DIR="$PWD/input" STATE_DIR="$PWD/state" OUTPUT_DIR="$PWD/output"
|
||||
export PUID="$(id -u)" PGID="$(id -g)"
|
||||
export AFRINIC_TAL_FILE=afrinic.tal AFRINIC_TA_FILE=afrinic.cer
|
||||
export APNIC_TAL_FILE=apnic.tal APNIC_TA_FILE=apnic.cer
|
||||
export ARIN_TAL_FILE=arin.tal ARIN_TA_FILE=arin.cer
|
||||
export LACNIC_TAL_FILE=lacnic.tal LACNIC_TA_FILE=lacnic.cer
|
||||
export RIPE_TAL_FILE=ripe.tal RIPE_TA_FILE=ripe.cer
|
||||
export CONFIG_FILE="$PWD/all5.toml"
|
||||
export INPUT_DIR="$PWD/input" STATE_DIR="$PWD/state/all5" OUTPUT_DIR="$PWD/output/all5"
|
||||
docker compose -f docker/compose.all5.yaml run --build --rm validator
|
||||
```
|
||||
|
||||
| Template variable | Default | Applies to |
|
||||
| --- | --- | --- |
|
||||
| `PANDA_RPKI_WORKERS` | 8 | all5 and daemon object workers |
|
||||
| `PANDA_RPKI_REPO_WORKERS` | 8 | all5 and daemon transport workers |
|
||||
| `PANDA_RPKI_WORKER_QUEUE_CAPACITY` | 256 | all5 object queue |
|
||||
| `PANDA_RPKI_REPO_QUEUE_CAPACITY` | 256 | all5 daemon repository queue |
|
||||
| `PANDA_RPKI_HTTP_TIMEOUT_SECS` | 600 | all5 HTTP timeout (native CLI default is 300) |
|
||||
| `PANDA_RPKI_RRDP_SYNC_MODE` | auto | single-anchor and all5 |
|
||||
The application still receives only `validate --config`; workers, timeouts,
|
||||
logging and sync policy belong in `all5.toml`.
|
||||
|
||||
The all5 CCR is `OUTPUT_DIR/all5.ccr`; the single-anchor CCR is
|
||||
`OUTPUT_DIR/result.ccr`. Reuse `STATE_DIR` and select new `OUTPUT_DIR` values
|
||||
to retain multiple cycles. These templates take no bundled RIR input files.
|
||||
## Daemon
|
||||
|
||||
## All-five daemon service
|
||||
Daemon TOML paths are also container paths. `state-root` owns run directories,
|
||||
protocol state and the `latest` pointer:
|
||||
|
||||
The all-five daemon template combines the five regional TAL/TA pairs with the
|
||||
continuous daemon controller. Prepare the same `input/` directory used by the
|
||||
all-five one-shot example, then run:
|
||||
```toml
|
||||
config-version = 1
|
||||
mode = "daemon"
|
||||
state-root = "/data"
|
||||
interval-secs = 600
|
||||
retain-runs = 10
|
||||
run-timeout-secs = 1800
|
||||
shutdown-grace-secs = 30
|
||||
|
||||
[[anchors]]
|
||||
id = "anchor"
|
||||
tal = "/input/anchor.tal"
|
||||
# ta = "/input/anchor.cer" # uncomment for fixed TA mode
|
||||
```
|
||||
|
||||
Run the daemon template:
|
||||
|
||||
```bash
|
||||
mkdir -p data/all5-daemon
|
||||
export INPUT_DIR="$PWD/input" DAEMON_DIR="$PWD/data/all5-daemon"
|
||||
export AFRINIC_TAL_FILE=afrinic.tal AFRINIC_TA_FILE=afrinic.cer
|
||||
export APNIC_TAL_FILE=apnic.tal APNIC_TA_FILE=apnic.cer
|
||||
export ARIN_TAL_FILE=arin.tal ARIN_TA_FILE=arin.cer
|
||||
export LACNIC_TAL_FILE=lacnic.tal LACNIC_TA_FILE=lacnic.cer
|
||||
export RIPE_TAL_FILE=ripe.tal RIPE_TA_FILE=ripe.cer
|
||||
mkdir -p daemon-state
|
||||
export CONFIG_FILE="$PWD/daemon.toml"
|
||||
export INPUT_DIR="$PWD/input" DAEMON_DIR="$PWD/daemon-state"
|
||||
export PUID="$(id -u)" PGID="$(id -g)"
|
||||
docker compose -f docker/compose.all5-daemon.yaml up -d --build
|
||||
docker compose -f docker/compose.all5-daemon.yaml logs -f validator
|
||||
docker compose -f docker/compose.daemon.yaml up --build
|
||||
```
|
||||
|
||||
The template uses a 60-second interval by default, keeps 10 completed runs,
|
||||
and leaves the daemon running until it is stopped. It writes each run below
|
||||
`DAEMON_DIR/runs/` and keeps shared protocol state below `DAEMON_DIR/state/`.
|
||||
The default diagnostic format is `text`, with a source file and line appended
|
||||
to each diagnostic record; select `json` explicitly for machine consumers.
|
||||
Set `PANDA_RPKI_INTERVAL_SECS` only when a different interval is intended. Stop
|
||||
the service without deleting its data with:
|
||||
For an all-RIR daemon use `docker/compose.all5-daemon.yaml` with an all-RIR
|
||||
TOML. Stop the whole Compose service for an upgrade so the state-root lock and
|
||||
validator child are released; do not delete `daemon-state`.
|
||||
|
||||
## Configuration and persistence
|
||||
|
||||
Run `docker compose ... run --rm validator validate --config ... --check-config`
|
||||
only when the image command is overridden deliberately; the normal templates
|
||||
already pass the config. Check/print never download TA files or open RocksDB.
|
||||
Successful validate publication, when `publish-dir` is configured, is an
|
||||
immutable `publish/runs/<id>` plus `publish/latest`; daemon publication uses its
|
||||
existing `state-root/runs/run_<seq>` directory. Cache files are written beside
|
||||
the protocol state as `<state>.ta-cache/`.
|
||||
|
||||
If a host path is not writable by the selected UID/GID, pre-create it and fix
|
||||
ownership. Preserve existing state and run history when changing images. Verify
|
||||
`summary.json`, `result-complete.json`, `vrps.csv`, `vaps.csv`, timing files and
|
||||
the `latest` link after a deployment.
|
||||
|
||||
## Complete configuration examples
|
||||
|
||||
Copy a template before editing it; set `CONFIG_FILE` to the copy's absolute path.
|
||||
These templates use automatic **TA certificate** refresh, text/info logs and
|
||||
`require-complete = true`. They never download or update TAL files.
|
||||
|
||||
| Compose file | Complete TOML |
|
||||
| --- | --- |
|
||||
| `compose.yaml` | [validate.toml](../docker/examples/validate.toml) |
|
||||
| `compose.all5.yaml` | [validate-all5.toml](../docker/examples/validate-all5.toml) |
|
||||
| `compose.daemon.yaml` | [daemon.toml](../docker/examples/daemon.toml) |
|
||||
| `compose.all5-daemon.yaml` | [daemon-all5.toml](../docker/examples/daemon-all5.toml) |
|
||||
|
||||
For example, from the repository root:
|
||||
|
||||
```bash
|
||||
docker compose -f docker/compose.all5-daemon.yaml stop
|
||||
```
|
||||
|
||||
## Upgrade a daemon deployment
|
||||
|
||||
An upgrade replaces the image and recreates the container. It does not replace
|
||||
the host data directory. Keep the same `DAEMON_DIR`, Compose project, TAL/TA
|
||||
inputs and controller settings so the new image can resume the existing
|
||||
protocol state. Do not run two writable daemons against the same state root.
|
||||
|
||||
Run the following from the deployment directory that owns the Compose file. Use
|
||||
a unique image tag for every candidate so the image used by a run is auditable:
|
||||
|
||||
```bash
|
||||
export COMPOSE_FILE="${COMPOSE_FILE:-docker/compose.all5-daemon.yaml}"
|
||||
export COMPOSE_PROJECT_NAME=panda-rpki-all5
|
||||
export PANDA_RPKI_IMAGE=panda-rpki:2026-09-11-logging
|
||||
export SOURCE_DIR=/path/to/panda-rpki-oss
|
||||
|
||||
# Keep the existing INPUT_DIR, DAEMON_DIR, TAL/TA variables and settings.
|
||||
docker compose -p "$COMPOSE_PROJECT_NAME" -f "$COMPOSE_FILE" ps
|
||||
test "$(jq -r .state "$DAEMON_DIR/daemon-status.json")" = sleeping
|
||||
|
||||
# Build from the source tree before stopping the running service.
|
||||
docker build -f "$SOURCE_DIR/docker/Dockerfile" -t "$PANDA_RPKI_IMAGE" "$SOURCE_DIR"
|
||||
docker image inspect "$PANDA_RPKI_IMAGE" --format '{{.Id}}'
|
||||
|
||||
# Save configuration and create a consistent stopped-state backup.
|
||||
backup="upgrade-backup-$(date -u +%Y%m%dT%H%M%SZ)"
|
||||
mkdir -p "$backup"
|
||||
cp "$COMPOSE_FILE" "$backup/compose.yaml"
|
||||
if test -f .env; then cp .env "$backup/env"; fi
|
||||
docker compose -p "$COMPOSE_PROJECT_NAME" -f "$COMPOSE_FILE" stop
|
||||
cp -a "$DAEMON_DIR/state" "$backup/state"
|
||||
cp -a "$DAEMON_DIR/daemon-status.json" "$DAEMON_DIR/lifecycle.json" "$backup/"
|
||||
|
||||
# Recreate the same service with the new image; bind-mounted data is retained.
|
||||
docker compose -p "$COMPOSE_PROJECT_NAME" -f "$COMPOSE_FILE" up -d --no-build --force-recreate
|
||||
docker inspect "$(docker compose -p "$COMPOSE_PROJECT_NAME" -f "$COMPOSE_FILE" ps -q validator)" \
|
||||
--format 'image={{.Config.Image}} running={{.State.Running}}'
|
||||
```
|
||||
|
||||
After the first upgraded run, verify that the run sequence advanced, the run
|
||||
completed, and the new log/outputs exist. The exact run directory is printed by
|
||||
the daemon status and can be selected with `find`:
|
||||
|
||||
```bash
|
||||
latest_run="$(find "$DAEMON_DIR/runs" -mindepth 1 -maxdepth 1 -type d -name 'run_*' | sort | tail -1)"
|
||||
test -s "$latest_run/run-summary.json"
|
||||
test -s "$latest_run/validator.log"
|
||||
test -s "$latest_run/result.ccr"
|
||||
grep -Eq '\[src/[^]]+\.rs:[0-9]+\]$' "$latest_run/validator.log"
|
||||
jq . "$latest_run/run-summary.json"
|
||||
```
|
||||
|
||||
The upgrade process preserves completed run directories until normal retention
|
||||
removes them. Archive important runs separately if they must outlive
|
||||
`PANDA_RPKI_RETAIN_RUNS`.
|
||||
|
||||
### Roll back
|
||||
|
||||
Stop the upgraded service before changing the image. Restore the previous
|
||||
Compose file and `.env`, or set `PANDA_RPKI_IMAGE` to the previously verified
|
||||
tag, then recreate the service with the same project and data directory:
|
||||
|
||||
```bash
|
||||
docker compose -p "$COMPOSE_PROJECT_NAME" -f "$COMPOSE_FILE" stop
|
||||
cp "$backup/compose.yaml" "$COMPOSE_FILE"
|
||||
if test -f "$backup/env"; then cp "$backup/env" .env; fi
|
||||
unset PANDA_RPKI_IMAGE
|
||||
docker compose -p "$COMPOSE_PROJECT_NAME" -f "$COMPOSE_FILE" up -d --no-build --force-recreate
|
||||
```
|
||||
|
||||
If the new binary changed the state schema or wrote incompatible state, stop the
|
||||
service and move the current state aside before restoring the matching
|
||||
stopped-state backup:
|
||||
|
||||
```bash
|
||||
mv "$DAEMON_DIR/state" "$DAEMON_DIR/state-incompatible-$(date -u +%Y%m%dT%H%M%SZ)"
|
||||
cp -a "$backup/state" "$DAEMON_DIR/state"
|
||||
```
|
||||
|
||||
Never delete `DAEMON_DIR` or use `docker compose down -v` as part of a routine
|
||||
upgrade. Check [state compatibility](command-line-reference.md#state-and-network)
|
||||
before deploying a binary with storage changes.
|
||||
|
||||
## Single-anchor daemon service
|
||||
|
||||
```bash
|
||||
mkdir -p data/daemon
|
||||
export INPUT_DIR="$PWD/input" DAEMON_DIR="$PWD/data/daemon"
|
||||
export TAL_FILE=anchor.tal TA_FILE=anchor.cer
|
||||
cp docker/examples/daemon-all5.toml daemon.toml
|
||||
export CONFIG_FILE="$PWD/daemon.toml"
|
||||
export INPUT_DIR="$PWD/input" DAEMON_DIR="$PWD/daemon-state"
|
||||
mkdir -p "$DAEMON_DIR"
|
||||
export PUID="$(id -u)" PGID="$(id -g)"
|
||||
export PANDA_RPKI_INTERVAL_SECS=600 PANDA_RPKI_RETAIN_RUNS=10
|
||||
docker compose -f docker/compose.daemon.yaml up -d --build
|
||||
docker compose -f docker/compose.daemon.yaml logs -f validator
|
||||
# Stop gracefully; persistent host data remains available.
|
||||
docker compose -f docker/compose.daemon.yaml stop
|
||||
docker compose -p panda-all5 -f docker/compose.all5-daemon.yaml up -d --build
|
||||
```
|
||||
|
||||
Defaults: interval 60 seconds, retain 10, `PANDA_RPKI_RUN_TIMEOUT_SECS=0`
|
||||
(disabled), log level `info`, log format `text`. The daemon template passes
|
||||
`PANDA_RPKI_LOG_LEVEL` and `PANDA_RPKI_LOG_FORMAT` into the container.
|
||||
It restarts unless stopped and allows 40 seconds for shutdown, exceeding the
|
||||
controller's default 30-second grace plus termination wait.
|
||||
For single validation, `/state` is the writable mount parent. Set
|
||||
`rrdp-state-dir = "/state/repository"` so both `/state/repository` and its
|
||||
sibling `/state/repository.ta-cache` are persistent and writable. Existing
|
||||
fixed-mode deployments with `rrdp-state-dir = "/state"` must plan a stopped
|
||||
state-layout migration or mount `/state.ta-cache` separately before enabling
|
||||
automatic mode. Do not silently point an existing database at an empty path.
|
||||
Daemon needs no such migration: `/data/state` and `/data/state.ta-cache` already
|
||||
share the writable `/data` mount.
|
||||
|
||||
For multiple anchors, append TAL/TA pairs after `--` in the daemon service's
|
||||
command. For other validator options, edit that same list. A finite run can
|
||||
be invoked with `docker compose run --rm validator daemon ...` using the
|
||||
[daemon CLI](command-line-reference.md#daemon); use `--max-runs` before `--`.
|
||||
## Graceful stop, edit and reload
|
||||
|
||||
Compose variables are expanded into arguments; only the two documented log
|
||||
environment variables are read directly by the binary. For single-anchor/all5
|
||||
logs, pass them with `docker compose run -e PANDA_RPKI_LOG_LEVEL=debug ...`.
|
||||
Use the same project name, Compose file and environment file on every command.
|
||||
The following assumes the `panda-all5` project created above:
|
||||
|
||||
```bash
|
||||
dc() { docker compose -p panda-all5 -f docker/compose.all5-daemon.yaml "$@"; }
|
||||
dc stop --timeout 40 validator
|
||||
dc ps -a
|
||||
cp -a "$CONFIG_FILE" "$CONFIG_FILE.bak.$(date -u +%Y%m%dT%H%M%SZ)"
|
||||
```
|
||||
|
||||
Edit the existing top-level field to `log-format = "text"`. To enable automatic
|
||||
TA refresh, remove each desired anchor's `ta` field; keep its `id` and `tal`.
|
||||
`ta-refresh-policy = "allow-valid-cache"` allows a revalidated cache fallback
|
||||
and marks that run partial; `"require-fresh"` rejects the fallback. Missing or
|
||||
invalid cache cannot satisfy the first automatic run if all downloads fail.
|
||||
|
||||
Check the changed file and recreate the service:
|
||||
|
||||
```bash
|
||||
dc run --rm --no-deps validator daemon --config /config/daemon.toml --check-config
|
||||
dc run --rm --no-deps validator daemon --config /config/daemon.toml --print-config
|
||||
# Continue only after Configuration valid. and the expected effective settings.
|
||||
dc up -d --no-build --force-recreate validator
|
||||
dc logs --since 2m validator
|
||||
```
|
||||
|
||||
Recreation is intentional: editors and `sed -i` can replace the host file's
|
||||
inode, while an existing single-file bind mount may retain the old file.
|
||||
`start` or `restart` alone is not the documented configuration reload procedure.
|
||||
Recreation retains bind-mounted state and run history.
|
||||
|
||||
SIGTERM prevents further cycles and allows the active child up to
|
||||
`shutdown-grace-secs` (30 here) to finish. If it does not finish, the controller
|
||||
sends TERM, then KILL after another 2 seconds. Docker's 40-second timeout leaves
|
||||
room for controller cleanup. It is not an unlimited wait for the current cycle.
|
||||
To avoid interrupting a long cycle, stop during the daemon's sleeping interval.
|
||||
`exited` confirms the container stopped; exit 3 means the controller recorded
|
||||
partial runs under `require-complete`, and does not mean stop failed. Inspect
|
||||
lifecycle logs to establish whether the last child finished or was interrupted.
|
||||
|
||||
The controller logs are in `docker compose logs`; child diagnostics are in
|
||||
`data/runs/run_XXXXXX/validator.log` on the host. Existing logs keep their original
|
||||
format. JSON summary/metadata files remain JSON even with text diagnostics.
|
||||
`latest` exists only after a complete success; partial runs do not create or
|
||||
replace it, including the first run after upgrading an old state root.
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
# Getting started
|
||||
|
||||
For every field, default, constraint and complete example, see the [TOML configuration reference](configuration.md)。
|
||||
|
||||
Panda RPKI v0.1.0 is a Linux command-line application. You can use Docker without
|
||||
installing Rust, or build a native binary. It requires outbound HTTPS to RPKI
|
||||
repositories, a writable state directory, and enough disk space for repository
|
||||
@@ -7,10 +9,11 @@ objects and outputs. Resource use depends on the selected trust anchors.
|
||||
|
||||
## Prepare trust anchors
|
||||
|
||||
A trust anchor defines what you trust. Obtain its TAL from the responsible RIR
|
||||
and obtain the current DER certificate from a certificate URI in that TAL.
|
||||
Panda RPKI checks that the certificate matches the TAL public key. It takes
|
||||
both files as explicit inputs; it does not refresh the supplied TA file for you.
|
||||
A trust anchor defines what you trust. Obtain its TAL from the responsible RIR.
|
||||
Panda RPKI checks the TAL public key and either uses a configured DER certificate
|
||||
or refreshes a certificate from the TAL's HTTPS/rsync URI. Automatic refresh
|
||||
stores a validated last-known certificate beside the protocol state; it never
|
||||
changes the TAL itself.
|
||||
|
||||
For example, the [RIPE NCC trust-anchor page](https://www.ripe.net/manage-ips-and-asns/resource-management/rpki/ripe-ncc-rpki-trust-anchor-structure/)
|
||||
publishes the RIPE NCC TAL. From the project root:
|
||||
@@ -20,6 +23,7 @@ mkdir -p input
|
||||
curl --fail --location --proto '=https' --proto-redir '=https' \
|
||||
--connect-timeout 15 --max-time 120 \
|
||||
https://tal.rpki.ripe.net/ripe-ncc.tal -o input/anchor.tal
|
||||
# Optional: download a TA certificate only for fixed mode.
|
||||
curl --fail --location --proto '=https' --proto-redir '=https' \
|
||||
--connect-timeout 15 --max-time 120 \
|
||||
https://rpki.ripe.net/ta/ripe-ncc-ta.cer -o input/anchor.cer
|
||||
@@ -36,10 +40,11 @@ commands, input checks, and the filenames used by Compose.
|
||||
|
||||
## Docker first run
|
||||
|
||||
Follow the [README Quick start](../README.md#quick-start). It creates
|
||||
`output/summary.json`, `output/vrps.csv` and `output/result.ccr`. State is retained
|
||||
under `state/repository-db/`. View warnings in the terminal and inspect the
|
||||
summary to distinguish rejected objects from successful repository updates.
|
||||
Follow the [README Quick start](../README.md#quick-start). The only application
|
||||
argument is `--config`; all paths, anchors, workers and logging belong in that
|
||||
TOML file. It creates `output/summary.json`, `output/vrps.csv` and
|
||||
`output/result.ccr`. State is retained under `state/repository/repository-db/` and the
|
||||
automatic TA cache is a sibling `state/repository.ta-cache/` directory.
|
||||
|
||||
## Build from source
|
||||
|
||||
@@ -53,14 +58,30 @@ cargo build --locked --release
|
||||
target/release/panda-rpki --help
|
||||
```
|
||||
|
||||
Run with the same inputs:
|
||||
Create a configuration file (paths are relative to the file, or use absolute
|
||||
container paths):
|
||||
|
||||
```toml
|
||||
config-version = 1
|
||||
mode = "validate"
|
||||
out = "output/native"
|
||||
rrdp-state-dir = "state"
|
||||
ccr-out = "output/native/result.ccr"
|
||||
|
||||
[[anchors]]
|
||||
id = "anchor"
|
||||
tal = "input/anchor.tal"
|
||||
# ta = "input/anchor.cer" # uncomment for fixed mode
|
||||
```
|
||||
|
||||
Run with that configuration:
|
||||
|
||||
```bash
|
||||
target/release/panda-rpki validate \
|
||||
--tal input/anchor.tal --ta input/anchor.cer \
|
||||
--rrdp-state-dir state --out output/native \
|
||||
--ccr-out output/native/result.ccr
|
||||
target/release/panda-rpki validate --config validate.toml
|
||||
```
|
||||
|
||||
Use `validate --config validate.toml --check-config` before a run for a read-only local check, or
|
||||
`validate --config validate.toml --print-config` to inspect absolute paths, defaults and field sources.
|
||||
|
||||
For tests, install `python3-cryptography` and `openssl`. See
|
||||
[Development](development.md) and [Usage](usage.md) for next steps.
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
# Diagnostic logging
|
||||
|
||||
For every field, default, constraint and complete example, see the [TOML configuration reference](configuration.md)。
|
||||
|
||||
The validator writes diagnostics to stderr. Under daemon, that stream is saved
|
||||
as `runs/run_XXXXXX/validator.log`; it contains all enabled levels, not only errors.
|
||||
`process-output.txt` captures ordinary output and is normally empty. The daemon's
|
||||
own lifecycle diagnostics remain in the container log. No duplicate log forwarding
|
||||
is performed. Historical `stderr.log` files are not renamed.
|
||||
|
||||
CLI and both daemon Compose files default to `info` and `text`.
|
||||
TOML defaults and the shipped Compose TOML examples use `info` and `text`.
|
||||
Compose does not independently select the logging format.
|
||||
Text is written for people, with independently authored English sentences for
|
||||
run lifecycle, validation stages, progress, output files and failures. It does not
|
||||
enumerate event fields or translate event identifiers into prose. Progress reports
|
||||
@@ -23,8 +26,8 @@ not select the format. Text is not a stable machine-parsing interface.
|
||||
2026-09-11T10:45:36Z INFO [run 230] Validation completed in 82.0 seconds.
|
||||
```
|
||||
|
||||
Use `--log-format json` or `PANDA_RPKI_LOG_FORMAT=json` for machine consumers;
|
||||
the JSON event names and fields are unchanged. Both formats redact sensitive data.
|
||||
Set `log-format = "json"` in the TOML for machine consumers; the JSON event
|
||||
names and fields are unchanged. Both formats redact sensitive data.
|
||||
Text error reasons are limited to 240 Unicode characters with an explicit notice
|
||||
when shortened. Unknown extension/debug events retain a diagnostic identifier and
|
||||
their message, not an arbitrary field dump. Use JSON (and debug/trace as needed)
|
||||
@@ -79,8 +82,8 @@ unregistered literal call sites. Unknown library-supplied names default to debug
|
||||
|
||||
## Progress and volume
|
||||
|
||||
`--log-progress-interval-secs` overrides `PANDA_RPKI_LOG_PROGRESS_INTERVAL_SECS`,
|
||||
default `10`. `0` suppresses periodic events, not stage events. `off/error/warn`
|
||||
`log-progress-interval-secs` is configured in TOML and defaults to `10`. `0`
|
||||
suppresses periodic events, not stage events. `off/error/warn`
|
||||
do not create a progress thread. Queue snapshots are refreshed at most every 250ms.
|
||||
`statistics_age_ms` is the age of the queue/PP snapshot, not the repository event
|
||||
counters. `progress_stalled` means no observed completion for 30s, not proof of deadlock.
|
||||
@@ -122,3 +125,13 @@ The `jq` examples require JSON logging to have been explicitly enabled.
|
||||
|
||||
Retention removes completed run directories including their logs. Archive needed
|
||||
runs before the configured retention window expires. Summary history is append-only.
|
||||
|
||||
## Change an existing daemon to text
|
||||
|
||||
Set `log-format = "text"` at the TOML top level, before `[[anchors]]`.
|
||||
Keep `log-level = "info"` or the desired existing level. Do not use the removed
|
||||
`--log-format` flag or `PANDA_RPKI_LOG_FORMAT` environment override.
|
||||
TOML is read at process start, so stop and recreate the service as described in
|
||||
[Docker configuration reload](docker.md#graceful-stop-edit-and-reload).
|
||||
Each new validator child inherits the controller configuration; prior run logs
|
||||
and JSON summary/metadata files are not converted.
|
||||
|
||||
@@ -35,3 +35,13 @@ are not sufficient to reproduce an image.
|
||||
If runtime code or dependencies change, repeat end-to-end snapshot/delta and
|
||||
artifact verification. Documentation-only changes do not establish new runtime
|
||||
performance measurements; retain the revision associated with earlier results.
|
||||
|
||||
## Configuration documentation checks
|
||||
|
||||
Verify all four `docker/examples/*.toml` with the release binary's
|
||||
`--check-config` and render each matching Compose file with `docker compose config`.
|
||||
Confirm mandatory TOML, removed business flags/env overrides, text logging,
|
||||
automatic versus fixed TA certificates, and operator-maintained TALs are
|
||||
documented consistently. Validate containers need a writable parent for both
|
||||
protocol state and the sibling TA cache. Configuration reload instructions must
|
||||
recreate a container after replacing a single-file bind-mounted TOML.
|
||||
|
||||
@@ -1,9 +1,37 @@
|
||||
# Prepare all five RIR trust anchors
|
||||
|
||||
Panda RPKI requires a TAL and a matching DER-encoded TA certificate for each
|
||||
anchor. The TAL supplies the trusted public key; the certificate supplies the
|
||||
current trust-anchor certificate. A certificate alone is not a substitute for
|
||||
an independently obtained TAL. No RIR inputs are bundled with this project.
|
||||
For every field, default, constraint and complete example, see the [TOML configuration reference](configuration.md)。
|
||||
|
||||
Panda RPKI requires a TAL for each configured anchor. The TAL supplies the
|
||||
trusted public key and its certificate URI. You may pin a matching DER-encoded
|
||||
TA certificate in TOML, or omit `ta` and let Panda fetch, validate and cache the
|
||||
current certificate on each run. A certificate alone is not a substitute for an
|
||||
independently obtained TAL. No RIR inputs are bundled with this project.
|
||||
|
||||
## Automatic and fixed certificate modes
|
||||
|
||||
Automatic mode requires only an independently obtained TAL:
|
||||
|
||||
```toml
|
||||
# Top-level setting, before any [[anchors]] table:
|
||||
ta-refresh-policy = "allow-valid-cache"
|
||||
|
||||
[[anchors]]
|
||||
id = "ripe"
|
||||
tal = "input/ripe.tal"
|
||||
# No ta field: refresh the TA certificate at each validate run / daemon cycle.
|
||||
```
|
||||
|
||||
Add `ta = "input/ripe.cer"` inside that anchor to select fixed mode. Anchors can
|
||||
mix modes. Fixed files are never replaced by the automatic cache. The TAL itself
|
||||
is never automatically updated: operators maintain its URIs and trusted key.
|
||||
All download candidates and cached fallback certificates must pass TA validation,
|
||||
TAL key binding and validity checks. A valid-cache fallback yields partial;
|
||||
`require-fresh` disallows it. Check-config does not test download reachability.
|
||||
|
||||
The download/pair-check sections below are optional for fixed mode. Automatic
|
||||
mode follows the URIs actually present in the TAL; it does not invent HTTPS
|
||||
alternatives for an rsync-only TAL.
|
||||
|
||||
## Official sources
|
||||
|
||||
@@ -85,7 +113,7 @@ for rir in afrinic apnic arin lacnic ripe; do
|
||||
done
|
||||
```
|
||||
|
||||
## Download the TA certificates
|
||||
## Optional: download certificates for fixed mode
|
||||
|
||||
After checking that the URI lines match the table, run in the same Bash shell
|
||||
(which defines `fetch_https`):
|
||||
@@ -112,7 +140,7 @@ fetch_https https://rpki.apnic.net/repository/apnic-rpki-root-iana-origin.cer in
|
||||
Always verify the downloaded certificate against the independently obtained
|
||||
TAL, including when using this alternative endpoint.
|
||||
|
||||
## Check the pairs and run
|
||||
## Optional: check fixed TAL/TA pairs
|
||||
|
||||
The following checks DER parsing, expiration, and equality of the certificate's
|
||||
SubjectPublicKeyInfo with the TAL key. They are input sanity checks, not a full
|
||||
@@ -136,13 +164,15 @@ for rir in afrinic apnic arin lacnic ripe; do
|
||||
done
|
||||
```
|
||||
|
||||
You now have ten files in `input/`, named exactly as expected by the
|
||||
[all-five Compose example](docker.md#all-five-regional-anchors). For the
|
||||
single-anchor README example only, copy a chosen pair to `input/anchor.tal`
|
||||
and `input/anchor.cer`, or change the CLI arguments to use its RIR filenames.
|
||||
You now have five TALs and, if using fixed mode, five matching certificates in
|
||||
`input/`. Put those paths in the named `[[anchors]]` tables shown in the
|
||||
[usage example](usage.md#multiple-anchors-and-constraints). To use automatic
|
||||
refresh, omit the corresponding `ta` line; the first run requires outbound
|
||||
HTTPS/rsync access and later runs may use the valid keyed cache when policy is
|
||||
`allow-valid-cache`.
|
||||
|
||||
Keep inputs out of version control. Monitor certificate validity and RIR
|
||||
announcements; Panda RPKI does not refresh supplied TA files automatically.
|
||||
Stage and check updated pairs before replacing active inputs between runs.
|
||||
Keep inputs out of version control. Monitor TAL changes and RIR announcements.
|
||||
Panda RPKI never rewrites supplied TA files; automatic mode refreshes a separate
|
||||
cache. Stage and check updated pairs before replacing active inputs between runs.
|
||||
Never resolve a key mismatch by replacing the TAL key with the downloaded
|
||||
certificate's key: retrieve the current TAL from the RIR and investigate first.
|
||||
|
||||
196
docs/usage.md
196
docs/usage.md
@@ -1,110 +1,132 @@
|
||||
# Usage
|
||||
|
||||
Examples assume `panda-rpki` is on PATH; for a local build use
|
||||
`target/release/panda-rpki`. Prepare TAL/TA files as described in
|
||||
[Getting started](getting-started.md).
|
||||
For every field, default, constraint and complete example, see the [TOML configuration reference](configuration.md)。
|
||||
|
||||
## Snapshot and delta
|
||||
Panda RPKI reads one TOML file at process start. Copy the file to create a
|
||||
different profile; there is no command-line business-option or environment
|
||||
override.
|
||||
|
||||
Use a fresh state directory for an explicit snapshot:
|
||||
## Snapshot, delta and automatic refresh
|
||||
|
||||
```bash
|
||||
panda-rpki validate --tal input/anchor.tal --ta input/anchor.cer \
|
||||
--rrdp-state-dir state/anchor --rrdp-sync-mode snapshot \
|
||||
--out output/snapshot --ccr-out output/snapshot/result.ccr
|
||||
panda-rpki validate --tal input/anchor.tal --ta input/anchor.cer \
|
||||
--rrdp-state-dir state/anchor --rrdp-sync-mode delta \
|
||||
--out output/delta-01 --ccr-out output/delta-01/result.ccr
|
||||
```toml
|
||||
config-version = 1
|
||||
mode = "validate"
|
||||
out = "output/ripe"
|
||||
rrdp-state-dir = "state/ripe"
|
||||
rrdp-sync-mode = "auto"
|
||||
ccr-out = "output/ripe/result.ccr"
|
||||
publish-dir = "publish/ripe"
|
||||
|
||||
[[anchors]]
|
||||
id = "ripe"
|
||||
tal = "input/ripe.tal"
|
||||
# ta = "input/ripe.cer" # leave out to refresh from the TAL URI
|
||||
```
|
||||
|
||||
Subsequent runs reuse state and can use `auto`. Delta mode can include a
|
||||
protocol-required snapshot or noop. Check actual operation counters in the
|
||||
summary. Do not discard persistent state between scheduled runs.
|
||||
```bash
|
||||
panda-rpki validate --config validate.toml --check-config
|
||||
panda-rpki validate --config validate.toml
|
||||
```
|
||||
|
||||
An empty state selects a snapshot. After a successful run, `auto` can use
|
||||
delta updates; after an incomplete or failed run it recovers with `auto`.
|
||||
Explicit `snapshot` requires an empty state and `delta` requires an existing
|
||||
database. A valid downloaded TA is cached beside the state directory using the
|
||||
TAL public-key hash. Refresh failures may use that cache under
|
||||
`allow-valid-cache` and produce `partial`; use `require-fresh` to reject the
|
||||
fallback.
|
||||
|
||||
## Multiple anchors and constraints
|
||||
|
||||
```bash
|
||||
panda-rpki validate \
|
||||
--tal input/arin.tal --ta input/arin.cer --tal-id arin \
|
||||
--tal input/ripe.tal --ta input/ripe.cer --tal-id ripe \
|
||||
--parallel-max-repo-sync-workers-global 8 \
|
||||
--parallel-phase2-object-workers 8 \
|
||||
--rrdp-state-dir state/multi --out output/multi \
|
||||
--ccr-out output/multi/result.ccr
|
||||
Use one named `[[anchors]]` table per RIR. There is no positional TAL/TA pairing:
|
||||
|
||||
```toml
|
||||
config-version = 1
|
||||
mode = "validate"
|
||||
out = "output/all5"
|
||||
rrdp-state-dir = "state/all5"
|
||||
ccr-out = "output/all5/result.ccr"
|
||||
|
||||
[[anchors]]
|
||||
id = "afrinic"
|
||||
tal = "input/afrinic.tal"
|
||||
# ta = "input/afrinic.cer" # uncomment for fixed TA mode
|
||||
|
||||
[[anchors]]
|
||||
id = "apnic"
|
||||
tal = "input/apnic.tal"
|
||||
# ta = "input/apnic.cer" # uncomment for fixed TA mode
|
||||
|
||||
[[anchors]]
|
||||
id = "arin"
|
||||
tal = "input/arin.tal"
|
||||
# ta = "input/arin.cer" # uncomment for fixed TA mode
|
||||
|
||||
[[anchors]]
|
||||
id = "lacnic"
|
||||
tal = "input/lacnic.tal"
|
||||
# ta = "input/lacnic.cer" # uncomment for fixed TA mode
|
||||
|
||||
[[anchors]]
|
||||
id = "ripe"
|
||||
tal = "input/ripe.tal"
|
||||
# ta = "input/ripe.cer" # uncomment for fixed TA mode
|
||||
constraints = "input/ripe.constraints"
|
||||
```
|
||||
|
||||
Add further pairs in the same way. Optional resource constraints are read from
|
||||
the TAL-adjacent `.constraints` file, or specified with
|
||||
`--ta-constraints arin=input/arin.constraints`. Rules follow the WG profile
|
||||
listed in the [standards matrix](conformance-matrix.md).
|
||||
|
||||
A constraint file contains `allow`/`deny` followed by an IPv4/IPv6 prefix,
|
||||
address range, ASN or ASN range. Blank lines and `#` comments are allowed.
|
||||
For a synthetic test anchor, an example is:
|
||||
|
||||
```text
|
||||
# Example resources only: do not apply this policy to a production RIR.
|
||||
allow 192.0.2.0/24
|
||||
deny 192.0.2.128/25
|
||||
allow 2001:db8::/32
|
||||
allow 64496 - 64511
|
||||
```
|
||||
|
||||
Deny overlap rejects an EE resource; otherwise the resource must be fully
|
||||
covered by allow rules of its resource family. Unlisted resources are not
|
||||
implicitly allowed. An empty constraint file therefore differs from having
|
||||
no constraint file. Overlapping rules are normalized and may produce warnings.
|
||||
An omitted `constraints` field discovers a same-stem file beside the TAL. An
|
||||
explicit path must exist and parse. Constraint rules follow the profile in the
|
||||
[standards matrix](conformance-matrix.md).
|
||||
|
||||
## Continuous operation
|
||||
|
||||
```bash
|
||||
panda-rpki daemon --state-root data/daemon \
|
||||
--interval-secs 600 --retain-runs 10 -- \
|
||||
--tal input/anchor.tal --ta input/anchor.cer \
|
||||
--log-level info --log-format json
|
||||
Daemon configuration keeps the controller and validator settings together:
|
||||
|
||||
```toml
|
||||
config-version = 1
|
||||
mode = "daemon"
|
||||
state-root = "data/all5-daemon"
|
||||
interval-secs = 600
|
||||
# max-runs = 3 # uncomment for a finite three-cycle run
|
||||
retain-runs = 10
|
||||
run-timeout-secs = 1800
|
||||
shutdown-grace-secs = 30
|
||||
require-complete = true
|
||||
ta-refresh-policy = "allow-valid-cache"
|
||||
log-format = "text"
|
||||
log-level = "info"
|
||||
|
||||
[[anchors]]
|
||||
id = "ripe"
|
||||
tal = "input/ripe.tal"
|
||||
# ta = "input/ripe.cer" # uncomment for fixed TA mode
|
||||
```
|
||||
|
||||
The daemon runs in the foreground. It starts with snapshot for empty state and
|
||||
requests delta after successful runs. The interval starts after each cycle
|
||||
finishes. Add `--max-runs 3` before `--` for a finite run. SIGTERM requests a
|
||||
graceful stop. Restart with the same root to continue numbering and state.
|
||||
```bash
|
||||
panda-rpki daemon --config daemon.toml --check-config
|
||||
panda-rpki daemon --config daemon.toml
|
||||
```
|
||||
|
||||
Each cycle writes to `data/daemon/runs/run_000001/`, then `run_000002/`, etc.
|
||||
Retention deletes the oldest completed run directories beyond the configured
|
||||
limit, including their artifacts. Copy anything you need to retain elsewhere.
|
||||
The append-only summary history is not trimmed by retention.
|
||||
Each cycle writes `data/all5-daemon/runs/run_000001/`, including the generated
|
||||
`validator-config.toml`, CSV/CCR/summary/timing artifacts, process metrics and
|
||||
logs. The daemon points `data/all5-daemon/latest` at the newest successful run;
|
||||
partial and failed runs remain available for diagnosis. It chooses snapshot for
|
||||
empty state, delta after success and auto after partial/failed recovery. A
|
||||
finite daemon exits 2 if any run failed, 3 when only partial runs occurred and
|
||||
`require-complete` is true, otherwise 0.
|
||||
|
||||
## Outputs and diagnostics
|
||||
|
||||
`validator.log` is the per-run diagnostic log, not an error-only file.
|
||||
`process-output.txt` captures ordinary child output and is normally empty.
|
||||
Old runs keep their historical filenames; collectors support `stderr.log` as a fallback.
|
||||
Every ten seconds, info logs report the current stage and available progress counters.
|
||||
Use `--log-progress-interval-secs 0` to disable periodic events; stage events remain.
|
||||
`statistics_age_ms` identifies stale statistics; `progress_stalled` means no observed
|
||||
completion for thirty seconds, not a proven deadlock. Totals and percentages are not guessed.
|
||||
Events include `run_id` and, under daemon, `run_seq`. Controller logs remain separate.
|
||||
`summary.json` and `result-complete.json` describe the current attempt. Use the
|
||||
immutable `publish/latest` (validate with `publish-dir`) or daemon `latest` when
|
||||
consumers need a consistent group of files. `validator.log` contains structured
|
||||
diagnostics on stderr; `--print-config` is configuration JSON and does not
|
||||
contain validation payloads.
|
||||
|
||||
`vrps.csv` contains `asn,prefix,max_length`. CCR contains canonical state;
|
||||
duplicate routing payloads can collapse into a single CCR entry. Count raw
|
||||
rows and normalized unique payloads separately when comparing outputs.
|
||||
ASPA canonicalization groups providers by customer ASN.
|
||||
For path, state-layout, RRDP origin or permission errors, inspect the error
|
||||
first and preserve the existing state directory. Do not share a writable state
|
||||
directory between concurrent instances.
|
||||
|
||||
Use `--log-level debug` for diagnosis, or `trace` for detailed object/worker
|
||||
events. Logs are written to stderr and can be redirected independently from
|
||||
outputs. In daemon mode, inspect per-run `validator.log` and the controller's
|
||||
`daemon-status.json` and `run-summary.jsonl`.
|
||||
|
||||
| Symptom | Action |
|
||||
| --- | --- |
|
||||
| TAL/TA key mismatch or expired TA | Refresh the certificate from the TAL's official URI and check the selected pair. |
|
||||
| State-layout/schema error | Preserve the directory and select a new dedicated root for a compatible run. |
|
||||
| Snapshot refuses existing state | Use `auto`/`delta`, or choose a fresh directory for a new snapshot. |
|
||||
| Delta refuses empty state | Establish state with `auto` or `snapshot`. |
|
||||
| Permission denied in Docker | Pre-create writable host directories and use your UID/GID mapping. |
|
||||
| RRDP origin rejection | Inspect the publisher's notification/references; extra TLS roots do not bypass origin policy. |
|
||||
| Daemon root locked | Stop the other instance normally; do not delete its lock file. |
|
||||
| Unexpected counts or partial output | Inspect warnings and per-run status; use new output paths to avoid stale files. |
|
||||
|
||||
See the [CLI reference](command-line-reference.md) for precise defaults,
|
||||
timeouts, exit codes and recovery behavior.
|
||||
TAL files themselves are operator-maintained; automatic refresh changes only
|
||||
TA certificates in the cache. See [stop/edit/reload](docker.md#graceful-stop-edit-and-reload)
|
||||
for Docker shutdown semantics, text logging changes and switching anchor modes.
|
||||
|
||||
Reference in New Issue
Block a user