70.1.38. pepsi-tlsrpt

SMTP TLS Reporting (RFC 8460) daily reports

Manual section:

1

70.1.38.1.1. Name

pepsi-tlsrpt - daily SMTP TLS Reporting (RFC 8460) aggregate reports.

70.1.38.1.2. Synopsis

pepsi-tlsrpt [GLOBAL-OPTIONS] report [–date YYYY-MM-DD] [–dry-run]

pepsi-tlsrpt [GLOBAL-OPTIONS] prune [–older-than DAYS]

70.1.38.1.3. Description

pepsi-tlsrpt is the sender side of SMTP TLS Reporting (RFC 8460). As Pepsi delivers outbound mail, the relay stages (pepsi-stage-relay-to-internet(1) and pepsi-stage-relay-to-smarthost(1)) record the outcome of each TLS session — a success, or a classified failure (starttls-not-supported, certificate-host-mismatch, certificate-expired, certificate-not-trusted, validation-failure, sts-policy-invalid) — as an aggregate counter in the pepsi.tls_session table, keyed by UTC day, recipient (policy) domain, applied policy type (tlsa/sts/no-policy-found), MX host and result. This recording is enabled by [pepsi-tlsrpt] SEND_REPORTS and is skipped for a report message itself (the state.tlsrpt loop guard), so a report that hits a TLS error never spawns a report about a report.

Run once a day from cron, pepsi-tlsrpt report compiles a day’s counters into one RFC 8460 aggregate report per recipient domain, looks up that domain’s advertised reporting address (the rua field of its _smtp._tls TXT record) and ships the gzip-compressed JSON report there: by e-mail for a mailto: target (the report is injected into the pipeline at REPORT_STAGE so it is DKIM-signed and relayed like any other message), or by HTTPS POST (with Content-Type: application/tlsrpt+gzip) for an https: target. Once a domain’s report is shipped, that day’s counters for it are deleted, so re-running for the same day is safe.

It connects to the shared database through the [pepsi-postgres] section and is configured by [pepsi-tlsrpt] (see pepsi.conf(5)). It is not a stage. Being a cron job it is normally started as root, in which case it continues as the pepsi service account; see Running as root.

The advertising half — publishing our own _smtp._tls TXT record so other senders report their TLS results toward our domains to us — is handled by pepsi-setup(1), which prints the record from [pepsi-tlsrpt] RUA.

70.1.38.1.4. Commands

report [–date YYYY-MM-DD] [–dry-run]

Compile and ship the reports for one UTC day, defaulting to yesterday.

–date YYYY-MM-DD

Report on this UTC day instead of yesterday.

–dry-run

Print each report’s JSON to standard output instead of sending it, and retain the counters (nothing is deleted). Useful for inspection.

prune [–older-than DAYS]

Delete pepsi.tls_session counters older than the retention window. With no flag the window is [pepsi-tlsrpt] RETAIN_DAYS (default 7). Reported days are already cleared by report; this only sweeps days that were never reported (e.g. a domain that advertises no rua).

–older-than DAYS

Override the retention window for this run.

70.1.38.1.5. Running as root

Pepsi gives every component its own PostgreSQL role, authenticated over the local socket by the operating-system account it runs as, and root is deliberately not one of them — which matters here because the daily job normally runs from root’s crontab. Rather than fail to connect, the tool detects that it was started as root and becomes the unprivileged pepsi service account — which owns pepsi.tls_session and may inject the report messages — before it connects. A crontab entry therefore needs no sudo -u pepsi.

The configuration file (and any @inline-secret@ fragment it references) is read before the switch, so a root-only configuration is still loaded normally.

If the pepsi account does not exist — an uninstalled source tree, a test rig — the identity is left untouched, a warning is logged, and the connection is attempted as the invoking user, so a setup in which root can reach the database keeps working.

70.1.38.1.6. Global Options

These global options precede the subcommand (a trailing flag is rejected).

-c FILE, –config FILE

Read the configuration from FILE instead of searching the default locations.

-L LOGLEVEL, –log LOGLEVEL

Set the logging verbosity. LOGLEVEL is one of error, warn, info, debug or trace (default: info).

-v, –verbose

Show log messages from all sources, including third-party libraries.

-h, –help

Print a usage summary and exit.

-V, –version

Print the version and exit.

70.1.38.1.7. Exit Status

0

Successful completion. Per-domain delivery problems (a lookup failure, an unreachable HTTPS endpoint) are logged and the run continues; the affected day’s counters are retained for the next run.

1

An error occurred: a malformed configuration, a missing required option (REPORT_FROM), or a failed database connection or query.

70.1.38.1.8. Examples

Send yesterday’s reports (typical cron invocation):

pepsi-tlsrpt -c /etc/pepsi/pepsi.conf report

Inspect what would be sent for a specific day without sending:

pepsi-tlsrpt -c /etc/pepsi/pepsi.conf report --date 2026-06-14 --dry-run

Prune counters older than 30 days:

pepsi-tlsrpt -c /etc/pepsi/pepsi.conf prune --older-than 30

A daily crontab entry (after midnight UTC, reporting the day just ended):

17 1 * * *  pepsi  pepsi-tlsrpt -c /etc/pepsi/pepsi.conf report && pepsi-tlsrpt -c /etc/pepsi/pepsi.conf prune

70.1.38.1.9. See Also

pepsi-setup(1), pepsi.conf(5), pepsi-stage-relay-to-internet(1), pepsi-stage-relay-to-smarthost(1), pepsi-config(1)

70.1.38.1.10. Bugs

Report bugs to the Pepsi issue tracker.