---
title: The pss.json settings file
url: https://doc2.pstreamer.tv/en/manual/extras/config_file.html
lang: en
product: Perfect Streamer
version: 2.0.1.264
---

# The pss.json settings file

This page describes the format of the `pss.json` file: how the document is built, what the service accepts when reading it and what is lost when it is written. It is addressed to those who edit the file directly or carry the settings to another node.

An edit to the file takes effect from the next start. To change the configuration of a running service, use the web interface or the HTTP API ([Managing the node over the HTTP API](api.md#extras-api)) — only they apply a change immediately and report the result.

The step-by-step procedures for editing, checking and carrying — [Editing, checking and carrying the settings](config_editing.md#extras-config-editing).

## What this file is

`pss.json` is the working settings file in the `/opt/pss/config` directory. The loading order, the fallback to `pss_back.json` and `pss_default.json` and the archive of damaged files in the `bad/` directory are described in [Behavior at startup and on configuration errors](../install/files.md#startup-config-errors).

One consequence of that order has to be held in mind before the file is opened in an editor: **a single unacceptable value costs every stream.** The file is not repaired piecemeal — it is refused whole, and the fallback leads to `pss_default.json`, which has no streams in it at all. The backup copy `pss_back.json` exists only where the settings have been restored through the web interface at least once ([Maintenance](../webui/administration.md#webui-maintenance)); the service keeps no regular backup. That is exactly why the file is checked before the service reads it.

The file is not a complete description of the configuration: it holds only the differences from the values the product was built with. What follows from that is in the next section; it is the most important thing to understand before editing.

In the same directory lies `pss.properties` — the global parameters of the process (the paths to the data and the logs, and the like). It is a “key=value” file with a syntax of its own, it has nothing to do with JSON, and nothing said here applies to it.

## The file holds only the differences from the defaults

When it writes the file, the service **skips every simple value that matches the default**. Only the differences are saved.

Three things follow from this, each of which happens in practice:

- **The file will not tell you how the service is configured.** A missing key means the default value, and that value itself is written nowhere in the file. To read the effective configuration whole, ask the running service for it over the HTTP API: there every key is returned, including the ones left at their default.
- **Writing a key with its default value is pointless.** Such a value is accepted, and at the next save of the file it disappears.
- **A change of a default value between versions changes behavior silently.** If the node has never overridden that key, it is not in the file — and after an update it will run on the new default from the very first start, and the file will say nothing about it. This is the main risk when carrying settings between versions, and the file itself will not reveal it. There is only one way to see such a change: read the effective configuration of both versions over the HTTP API, where the default values are returned as well.

The skipping applies only to single values. The sections and the lists themselves are always written, even when nothing is left inside: `"user-default": {}` is a section whose keys are all at their defaults, and `"accept-stream": []` is an empty list written by the same rule. Empty brackets say neither that the setting has been given nor that it was skipped: look at the meaning of the particular key.

## The structure of the document

The document is one JSON object. Its top-level members are the settings sections:

| Section | Type | What it describes |
| --- | --- | --- |
| `server` | object | The name and the role of the node, logging, maintenance. |
| `cluster` | object | Meshwork: the addresses, names and secrets of the neighboring nodes. |
| `user-default` | object | Reserved, holds no keys yet. |
| `user` | array | The accounts of stream receivers and partners. |
| `web-server` | object | The web interface and its accounts. |
| `http-server` | object | The delivery of streams over HTTP. |
| `epg-server` | object | The delivery of the program guide. |
| `cs` | object | External subscriber-management servers. |
| `mosaic` | object | Turning the mosaic on. |
| `epg` | object | The collection of the program guide and its sources. |
| `alerter` | object | The alert thresholds and the delivery addresses. |
| `acme` | object | The automatic acquisition of certificates. |
| `dvb-adapter` | array | DVB receiver cards. |
| `dvr-storage-list` | object | DVR archive storages. |
| `stream` | array | Streams. |
| `stream-adaptive` | array | Adaptive bitrate groups. |

Top-level arrays always hold objects. Inside sections and entries there are also plain lists of values — numbers and strings; on those see Paired arrays are matched by position. The objects of the arrays in turn hold nested arrays of objects, so the greatest depth of the document is three levels:

```
stream[]  ->  input[]   ->  the keys of one input
          ->  output[]  ->  the keys of one output
```

The keys of the simple sections are optional to the last one, and the absence of a whole section is not an error.

Array entries are the exception. Besides `id`, every entry must carry its own anchor keys: a stream — `stream-name`, an input and an output — `type` and the address or path of the chosen transport, a receiver card — `name`, a storage — `name` and `dir-path`, an account of the web interface and of the program guide — `login` and `password`, a program-guide source — `name` and `source`. Omitting any of them discards the whole file. The schema checks these keys, so a check before the start will catch such an entry.

The reference for the individual keys — the type, the range and the default of each — is in the reference document for the HTTP API ([Reference documents](api.md#extras-api-docs)). It is deliberately not repeated here: two copies of one reference diverge within a single release.

## What the service does when it reads the file

The reading is deliberately uneven: in some cases the service forgives the error, in others it refuses the whole file — its first duty is to bring the node up. The difference between a typo you will notice and a typo you will not lies exactly there.

### Accepted, but not as the person editing intended

| What is in the file | What the service does |
| --- | --- |
| An unknown key | **Ignored.** A warning is written to the log with the name of the key and of the section it is addressed to (for an array entry the array is named, not the entry itself). The setting you wanted to change simply does not change, and a typo in a key name is invisible until the log has been read. The key disappears from the file at the next save of the configuration, but does not itself cause a save and may lie in the file for a long time. |
| A key is absent | The default value applies. Not an error. |
| A section is absent | All of its keys take their default values. Not an error. |
| The same key twice in one section | The last one silently wins. Neither an error nor a warning. |
| A number, or `true` and `false`, in quotes | Accepted: the value is read as text and parsed. The schema, however, will refuse such a value, so numbers and flags are written without quotes. |
| A number out of range | **Clamped to the nearest edge** with a warning in the log naming the key, the value that was read and the edge that was applied. After loading, the service re-saves the file with the corrected value, so at the next start the warning is not repeated. The same value sent over the HTTP API is not corrected but refused with an error. |
| An array where a single value is expected | **Ignored entirely, without a single line in the log.** The setting stays at its default and no diagnostic appears at all. |

Errors of shape around lists, and a repeated key, are the cases that pass in complete silence: the log will say nothing about them. They are the main argument for checking the file against the schema before the start.

> **Note**
>
> A key that this build does not support also turns out to be unknown. On a node whose build cannot receive DVB, the `dvb-adapter` section of a carried-over file becomes unknown in its entirety: one warning in the log — and at the next save it disappears from the file.

### Refused together with the whole file

Each of these cases stops the loading. The file is moved into the `bad/` directory and the service moves on to the next file in order ([Behavior at startup and on configuration errors](../install/files.md#startup-config-errors)).

| What is in the file | Explanation |
| --- | --- |
| A JSON syntax error | Any. |
| A `null` value | Anywhere and for any key. `null` is never accepted: to return a setting to its default, delete the key. |
| A wrong shape of value | An object where a single value is expected; a single value where an object or a list of objects is expected. |
| A number or some other word instead of a flag | Boolean keys take only `true` and `false` — in quotes or without. Neither `1` and `0` nor `"yes"` and `"no"` are accepted. |
| A string longer than allowed | Length limits, unlike numeric ranges, are never truncated. |
| A fractional number where an integer is required | The value does not parse as an integer, and the loading stops. The same for a string that does not read as a number. |
| An array entry without an anchor key | Besides `id`, an entry must carry its own required keys (The structure of the document). |
| An array entry without an `id` | The identifier is required. The exception is the `stream` array: there a missing `id` is read as `0`, and that is an admissible value, so only the second entry without an identifier will be refused, as a duplicate. |
| A duplicated `id` | Two entries of one array with the same identifier. |
| A repeat of a value declared unique | A number of arrays require a key to be unique among their entries: account names, the names and paths of storages, stream names, source addresses and others. |
| An empty value where text is required | Inside array entries this requirement is strict; in the simple sections it is not observed everywhere, and the leniency should not be relied on. |
| A value that failed the section check | Some sections check their values as a whole, and such a check also stops the loading: inadmissible characters or an excess of length in the node name and the domain name, an unknown logging level, an incorrectly written additional domain, a mismatched number of entries in the paired Meshwork arrays, a mismatched length of the lists of names and values of environment variables. |

### The log is part of the procedure

The errors in the first table do not prevent a start, the errors in the second one stop it. The only place where the first are visible is the log after the first start. Any line about an ignored key or a clamped value means the file says something other than what you wrote in it.

## Rules that are not visible in the file

These are properties of the reading, not of the syntax. The file may be flawless JSON, pass every check of the previous section, and still mean something other than what it looks like.

### The order of the keys inside an object matters

Keys are applied in the order they are written. In several places a key **determines which keys exist at all further down the same entry**, and must therefore stand before them. A key written above its determining key is not yet recognized at the moment of reading and is discarded as unknown — with a warning in the log and without a loading error.

That is how these work:

- `type` in an input or output entry — it chooses the transport and everything that belongs to it;
- `mpts` and `stream-name` in a stream entry. `mpts` chooses the kind of stream and must precede the `input` and `output` arrays among other things, while `stream-name` opens the OTT, archive and multiplex parameters if there is no `mpts` key in the entry. The default of the `enable-mosaic` key, taken from `mpts`, is settled at the moment `mpts` is read (or, in its absence, `stream-name`): an explicitly given `enable-mosaic` above that point is overwritten by that value, below it is kept;
- `type` and `mode` in a DVB card entry — together they determine the set of configuration parameters, and both must stand before the `name` key.

One exception to the general rule: if the `input` and `output` arrays stand above `mpts`, the inputs and outputs are built as for a single-program stream, and a type admissible only for a multi-program stream leads to a refusal of the whole file rather than to a warning.

A file written by the service itself always satisfies these rules: the service emits the keys in a fixed, safe order. Only a file whose order has been changed by hand is vulnerable. JSON Schema has no notion of order, so this is not checked by the schema. The practical rule is simple: **do not move anything** — keep the order in which the service wrote the file.

### Identifiers are set by hand

Every entry of every array has an `id` key. Identifiers are assigned automatically only when an entry is created over the HTTP API; when the file is read, nobody assigns them.

An entry added by hand therefore **must** carry an explicit `id`:

- it is required in any array — without it the whole file is refused;
- it must be unique inside its own array;
- the smallest admissible value is `1` everywhere except the `stream` array, where `0` is admissible too.

For the `stream` array a trap follows from this: a missing `id` is read there as `0`, that is, as a genuine identifier. The first entry without an `id` will pass, the second will collide with it and discard the whole file. For the same reason a stream with `id` `0` is written into the file with no `id` line at all — that is not a writing error but a consequence of zero being the default value here.

The uniqueness of identifiers cannot be expressed in JSON Schema, so this is one of the few rules the schema will not check for you. A ready-made command for finding duplicates is in [The checks the schema does not do](config_editing.md#extras-config-editing-checks).

### The order of entries in an array is not preserved

The service sorts the large lists at every read, each by its own key: streams by display name, the inputs and outputs of a stream by the order key, accounts by login, storages and receiver cards by name. Whatever order you write such entries in, the saved file will differ. Do not read meaning into their order: where the sequence matters there is a key of its own for it.

The rule is not universal, and two exceptions are worth noting:

- a few lists keep the order from the file — in particular the adaptive bitrate groups and the subscriber-management servers;
- **plain lists of values are never reordered.** That matters: it is on their order that the paired arrays rest (Paired arrays are matched by position).

### Paired arrays are matched by position

Several settings are expressed as parallel arrays matched by number: entry N of one array relates to entry N of the others. That is how the addresses, names and secrets of the neighboring Meshwork nodes work, the names and values of environment variables, and the “was — became” lists when identifiers are reassigned. Deleting an entry from one array without deleting the corresponding entry from the others shifts everything that follows.

The schema will check that each array holds elements of the right type, but not that the lengths of the arrays match. The service checks that itself and discards the whole file when the lengths differ for the Meshwork peers, for the environment variables, for the “was — became” lists when PIDs are reassigned (`mpegts-pid-old` and `mpegts-pid-new`), for the language-change lists (`mpegts-lang-set-pid` and `mpegts-lang-set`) and for the descrambling keys (`biss-pnr` and `biss-key`). For the four RIST addresses (`rist-addr-*`) a difference in length does not stop the loading, but the input does not open and the reason is written to the log. A ready-made command for the check is in [The equal length of paired arrays](config_editing.md#extras-config-editing-parallel).

### Comments are read but not preserved

The reading admits block comments of the form `/* ... */` — they are handy while working on the file. Only that form: a line comment `//` is not supported and makes the file syntactically wrong, that is, discards it whole. For the same reason do not write the sequence `/*` inside a text value — it will be taken for the start of a comment.

Comments do not survive a save: the service builds the document anew every time from what it holds in memory, so the very first save erases them all. Treat them as notes for the duration of the edit, and write what has to survive into the `note` key, which most sections and entries have.

Strict JSON tools — including the validator from [Editing, checking and carrying the settings](config_editing.md#extras-config-editing) — will not parse a file with comments. Remove the comments before checking.

### Conditional sets of keys

Two keys act as switches that determine which keys are admissible beside them:

- In input and output entries `type` chooses the transport. Every transport has its own set of keys; a key of another transport is not recognized.
- In DVB card entries `type` chooses the broadcasting system and `mode` the operating mode. Together they determine the set of configuration keys, down to whether there are any converter keys at all.

The schema reproduces these conditions and will refuse a key that does not belong to the chosen variant. The only case it cannot express is a key whose **shape** depends on a switch in the enclosing object: in a multi-program stream the descrambling key (`biss-key`) is written as a list, and in a single-program stream as a single value. The schema accepts both forms wherever the key occurs; only the service picks the right one.

## Values that must not be passed on

The file holds passwords and keys in the clear. Before handing the configuration to anyone at all — a colleague, a support request, a ticketing system, a public repository — replace the values of:

- the account passwords in the web interface, program guide and stream receiver sections, the password of the subscriber-management server, and the login and password of the program-guide source;
- the node’s own secret and the secrets of the neighboring Meshwork nodes;
- the transport passphrases and the client passwords of the PS1 and SRT inputs, the password of the RTSP input, the login and password of the HLS/HTTP input;
- the keys and key identifiers of content protection and the shared secrets;
- the descrambling keys;
- the messaging-service bot token and the password of the mail account;
- the binding key of the certificate authority.

Two keys are not named after secrets but regularly contain them: the publishing address of an output to an external site, and the source address of an input, if the credentials are written straight into the link.

The list grows with every new transport, so do not rely on it as exhaustive: before sending the file, search it for `password`, `secret`, `key`, `token` and `passphrase`, and look through every link.

The file is not the only route to these values: over the HTTP API they are readable by any account on the node, including a read-only role ([Access](api.md#extras-api-access)).

> **Warning**
>
> Replacing a secret with an empty string is not always safe: some of these keys do not accept an empty value, and the file will be refused whole. Substitute an obvious replacement of a plausible length.

## Checking against the JSON Schema

A machine-readable description of the settings file in JSON Schema format is published with the documentation. It catches a whole class of errors that the service itself swallows in silence — above all a typo in a key name and an array written instead of a single value.

### Two schema files

| File | Purpose |
| --- | --- |
| `pss.schema.json` | Strict. Every key must be one of those declared by the product. Used for a file intended for the version named in the header of the schema. |
| `pss.compat.schema.json` | Permissive. Types, ranges, enumerations and required keys are still checked, but keys the product does not know are skipped. The first pass when carrying settings from another version, where unknown keys are expected rather than suspicious. |

Both schemas carry the product version they were generated for. A configuration is only meaningfully checked against the schema of the version that will read it. Checking against the schema of another release gives a confident and wrong answer.

> **Warning**
>
> The permissive schema skips more than unfamiliar keys. The belonging of a key to the chosen variant (Conditional sets of keys) rests in the schema on the same mechanism, so a permissive check also passes a genuine key written into the wrong input type, the wrong card mode or the wrong kind of stream — and with it, its own range goes unchecked as well. The permissive schema is only the first pass; the last word always belongs to the strict one.

> **Note**
>
> The schemas are part of the documentation set, not of the product: there is no copy in the settings directory of a running node, and none is needed there. They are published on the documentation site — [https://doc2.pstreamer.tv/schema/](https://doc2.pstreamer.tv/schema/), one directory per version. Take the schema for your version and keep it on the machine where you edit the file.
>
> The address written inside the schema itself, in the `$id` key, is its identifier and not an instruction to download anything: checking a file works without network access too.

### What the schema checks

- key names — a typo becomes an error instead of a silent omission;
- the types of the values, including an array written instead of a single value;
- numeric ranges and text length limits;
- closed sets of admissible values;
- the presence of the required keys, above all `id` and `type`;
- the belonging to a variant — a key of a foreign transport or of a foreign broadcasting system will be flagged.

### What the schema does not check

- the order of the keys inside an object (The order of the keys inside an object matters);
- the uniqueness of identifiers and of keys declared unique (Identifiers are set by hand);
- the equal length of parallel arrays (Paired arrays are matched by position);
- the shape of a key that depends on a switch in the enclosing object (Conditional sets of keys);
- references between sections — whether the storage, source or card referred to by number actually exists;
- anything that depends on the machine: whether the path is writable, whether the port is free.

Everything listed is checked by the service itself when it reads the file, and most of it stops the loading. The schema narrows the gap but does not close it: a successful check means the file is correct and plausible, not that the service will accept it.

> **Note**
>
> The HTTP API contains a `/schema` family of requests that return lists of admissible values and of the hardware that was found — the input and output types supported by this build, the languages, the cards that were found, the transcoder devices. They have nothing to do with the `pss.schema.json` file, and one does not replace the other. The coincidence in the names is only a coincidence.

## Compatibility between versions

> **Warning**
>
> **Backward compatibility is not guaranteed.** An update may change the settings file, the schema and the HTTP API alike: the set and the names of the keys, the ranges of values, the shape of requests and responses. An update does not carry the settings over and does not warn about divergences. Check the file again after every update, and the scripts that work with the HTTP API — again after every update as well.

Individual keys are added, renamed and removed between releases, and the admissible ranges narrow. A removed key becomes unknown and is ignored, so the setting simply stops working; a new key acts on its default until it is written; a value that has fallen outside a narrowed range is clamped to the edge. The service reports none of the three.

**There is no version mark in the file.** Nothing inside it points to the release that wrote it, and the service performs no conversion when reading a file from an older or a newer build. Together with the sparseness of the file this means that a carried-over file is applied as it is.

The schema is therefore the only practical way to learn which keys of an existing file this release no longer understands. Check the file again after every update; the procedure is [Carrying the settings to another version](config_editing.md#extras-config-editing-migrate).
