70.1.37. pepsi-settings

manage per-address stage option overrides

Manual section:

1

70.1.37.1.1. Name

pepsi-settings - set, list and remove per-address configuration overrides.

70.1.37.1.2. Synopsis

pepsi-settings [GLOBAL-OPTIONS] set ADDRESS STAGE OPTION VALUE

pepsi-settings [GLOBAL-OPTIONS] unset ADDRESS STAGE [OPTION]

pepsi-settings [GLOBAL-OPTIONS] import ADDRESS SOURCE

pepsi-settings [GLOBAL-OPTIONS] get ADDRESS

pepsi-settings [GLOBAL-OPTIONS] list [–json]

pepsi-settings [GLOBAL-OPTIONS] remove ADDRESS

70.1.37.1.3. Description

pepsi-settings is the operator’s tool for the pepsi.settings table, which lets a stage’s options be overridden per e-mail address. A stage normally reads its options from its [stage-<name>] section in the configuration file; the settings table supplies overrides for messages to or from a particular correspondent, with the INI value acting as the default for any option the override does not mention.

Each row maps one lower-cased envelope address to a JSON object whose top-level keys are stage section names (stage-<name>) and whose values are objects of OPTION to value. For a given message the relevant address is the envelope sender when the message originates locally (state.local_origin), otherwise an envelope recipient. The address is matched exactly (no domain or subaddress fallback).

When the recipients of one inbound message resolve to different effective configurations for the stage about to run – whether the difference comes from this table or from a domain:/address: scope of the database overlay – the pipeline transparently splits the message into one row per distinct configuration, so each recipient is processed under its own settings; see pepsi-dispatch(1).

This tool is not a stage. It connects to the same database as the other components through the shared [pepsi-postgres] section and introduces no configuration of its own. When started as root it continues as the pepsi service account; see Running as root.

70.1.37.1.3.1. Relation to the database configuration overlay

The pepsi.settings table is the top layer of the configuration scope chain described in pepsi.conf(5):

configuration file  <  global  <  domain:<d>  <  address:<a>  <  pepsi.settings

The three middle layers live in a different table, pepsi.config_override, and are managed with pepsi-config(1). The two are deliberately not merged:

  • this table is written by account owners themselves, from their own mailbox, through pepsi-stage-edit-settings(1), restricted to the stage sections the operator allowed;

  • config_override defines the pipeline and is writable only through the pepsi-config PostgreSQL role, which no component that processes mail holds.

Keeping them apart is a security boundary rather than duplication: in one table, a bug in the per-address namespace check would stop being an override leak and become a user reconfiguring the mail server. pepsi-setup(1) verifies the grants against the live database after every install.

Where both mechanisms name the same option for the same message, this table wins – it is the higher layer, and what it may touch is already bounded by the operator’s EDITABLE_STAGES allowlist.

70.1.37.1.4. Commands

set ADDRESS STAGE OPTION VALUE

Set one option override. STAGE is the stage label (e.g. check-whitelist; a leading stage- is accepted and optional) and is stored as the section key stage-<name>. VALUE is stored as a string; the stage parses it exactly as it would the corresponding INI value (so a boolean uses YES/NO, a number its digits, and so on). The row and the stage section are created as needed.

unset ADDRESS STAGE [OPTION]

Remove one OPTION from the address’s STAGE section. With OPTION omitted, remove the whole stage section. An emptied section, and then an emptied row, are dropped automatically.

import ADDRESS SOURCE

Replace the address’s entire settings object with the JSON read from the file SOURCE, or from standard input when SOURCE is -. The JSON must be an object.

get ADDRESS

Print the address’s settings object as pretty JSON, or a notice if none exists.

list [–json]

List all rows. The default output is one address<TAB>JSON line per row; –json emits a JSON array of {address, settings} objects instead.

remove ADDRESS

Delete the address’s settings row entirely.

70.1.37.1.5. Validation

pepsi-setup(1) validates the table after installing the schema: every top-level key must name an existing [stage-<name>] section, and every option value must be a JSON scalar (string, number or boolean). An override keyed on a mistyped stage section is reported as an error rather than silently ignored.

70.1.37.1.6. 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. Rather than fail to connect and oblige you to remember sudo -u pepsi pepsi-settings , the tool detects that it was started as root and becomes the unprivileged pepsi service account — the account the stage scaffolding consults pepsi.settings as — before it connects.

Everything that happens before the connection still happens as the invoking user: the configuration file (with any @inline-secret@ fragment) is read first, and so is the JSON document given to import, so a root-only source path works.

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.37.1.7. 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.37.1.8. Exit Status

0

Successful completion.

1

An error occurred: a malformed configuration file, invalid JSON, or a failed database connection or query. The reason is written to the log.

70.1.37.1.9. Examples

Send mail to vip@example.com through a different whitelist:

pepsi-settings -c /etc/pepsi/pepsi.conf set vip@example.com check-whitelist WHITELIST_NAME vips

Block a different set of languages for one recipient:

pepsi-settings -c /etc/pepsi/pepsi.conf set bob@example.org block-language BLACKLIST 'ru,zh'

Inspect and then clear a recipient’s overrides:

pepsi-settings -c /etc/pepsi/pepsi.conf get bob@example.org
pepsi-settings -c /etc/pepsi/pepsi.conf unset bob@example.org block-language BLACKLIST

Load a whole object from a file:

pepsi-settings -c /etc/pepsi/pepsi.conf import vip@example.com /tmp/vip.json

70.1.37.1.10. See Also

pepsi-config(1), pepsi-dispatch(1), pepsi-stage-check-whitelist(1), pepsi-stage-block-language(1), pepsi-stage-edit-settings(1), pepsi.conf(5), pepsi-setup(1)

70.1.37.1.11. Bugs

Report bugs to the Pepsi issue tracker.