You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
ADN-DMR-Peer-Server/docs/en/server/user-guide/configuration.md

298 lines
18 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# Configuration
## Files and workflow
| File | Committed | Role |
|------|-----------|------|
| `adn-server.example.yaml` | Yes | Template — copy to `adn-server.yaml` and edit. |
| `adn-server.yaml` | **No** (gitignored) | Main server: systems, globals, logging, aliases, reports. **Hot-reload** via `SIGHUP` (see [Configuration](configuration.md#hot-reload-adn-serveryaml)). |
| `adn-voice.example.yaml` | Yes | Template for voice — copy to `adn-voice.yaml`. |
| `adn-voice.yaml` | **No** (typical) | Voice/TTS/recording; merged into `config["VOICE"]` at startup and **hot-reloaded** (~every 15 s) if the file changes. |
Run:
```bash
python adn-server.py -c /path/to/adn-server.yaml
```
Optional: `--logging LEVEL` overrides `LOGGER.LOG_LEVEL`.
If `adn-voice.yaml` sits next to `adn-server.yaml`, it is loaded automatically. You can also put a `VOICE:` block inside `adn-server.yaml`; the separate file is the usual way to change announcements without touching the main config.
### Hot reload (`adn-server.yaml`)
After editing the main config you can reload **without restarting** the process (active voice streams on unchanged UDP listeners are preserved):
```bash
kill -HUP $(pidof adn-server.py) # or: systemctl reload adn-server
```
Example unit: **`examples/systemd/adn-server.service`** (copy to `/etc/systemd/system/`; includes `ExecReload` for `systemctl reload`).
**Reload applies:** `GLOBAL`, `REPORTS`, `ALIASES`, **`LOGGER.LOG_LEVEL`** (without process restart), **`PROXY`** (timeouts, debug, block lists — not bind or target), **`SELF_SERVICE`** (PBKDF2 flags merged; enabling/disabling DB loops needs restart), per-system settings, **new/removed SYSTEMS** (including `GENERATOR` expansion/collapse and new OpenBridge legs), and updated bind addresses (listener restart for that system only).
**Not reloaded:** **`DATABASE`** (MariaDB pool and `peer_dynamic_tgs` bootstrap), `adn-voice.yaml` (separate 15 s loop), Python code, subscriber alias files (separate periodic reload). **BRIDGES** table is not rebuilt on reload — restart if bridge rules changed in a way that requires a full reset. **`PROXY.LISTEN_PORT`**, **`LISTEN_IP`**, and **`TARGET_SYSTEM`** require a **full restart** to take effect.
**Secrets:** Never commit real passphrases, security URLs, or `user_passwords.json` / `encryption_key.secret`. Use placeholders in templates and keep production files local.
---
## Architecture: what is a “system”?
Each entry under **`SYSTEMS`** is a named **logical link** (UDP endpoint) that speaks **HBP** (HomeBrew Protocol) to hotspots/repeaters, or **OpenBridge** to other servers. Names are free-form strings (`SYSTEM`, `ECHO`, `OBP-UK`, …) and are used in logs and in the **bridge table** (`BRIDGES`) to identify where traffic enters or leaves.
Three **modes** exist:
| Mode | Typical use | Listens | Connects upstream |
|------|-------------|---------|-------------------|
| **MASTER** | Conference server for one or more hotspots/repeaters | **Yes** — `IP` / `PORT`, peers register with passphrase | No (peers connect to you) |
| **PEER** | Hotspot/repeater or service (e.g. echo) behaving as a **client** of a MASTER | **Yes** — local `IP` / `PORT` | **Yes** — `MASTER_IP` / `MASTER_PORT` must point at a MASTER |
| **OPENBRIDGE** | Link to another **server** over OpenBridge (DMRD v1 / DMRE) | **Yes** — `IP` / `PORT` | **Yes** — `TARGET_IP` / `TARGET_PORT` (peer server) |
**MASTER** holds the **`PEERS`** table at runtime (hotspots that authenticated). **PEER** maintains **STATS** (connection, pings). **OPENBRIDGE** uses **NETWORK_ID**, **PASSPHRASE**, **TARGET_***, **PROTO_VER** / **VER**, and optional **ENHANCED_OBP**, **RELAX_CHECKS**, **TGID_ACL**.
A single process can run **several** systems at once (e.g. one MASTER for users, one ECHO for playback, one OBP to a partner network).
---
## `GLOBAL`
Server-wide defaults. Many keys can be overridden per system if `USE_ACL` (or similar) is set on that system.
| Key | Meaning |
|-----|---------|
| **PING_TIME** | Interval (seconds) for PEER keepalive / ping logic toward MASTER. |
| **MAX_MISSED** | How many missed pings before treating the PEER link as unhealthy (depends on implementation with STATS). |
| **USE_ACL** | If true, **REG_ACL**, **SUB_ACL**, **TGID_TS1_ACL**, **TGID_TS2_ACL** are applied (after processing into internal tuples). |
| **REG_ACL** | Access control for **registration** / peer IDs (`PERMIT:…` / `DENY:…`; see [ACL strings](#acl-strings)). |
| **SUB_ACL** | ACL for **subscriber** (radio) IDs on received traffic. |
| **TGID_TS1_ACL** | ACL for **talkgroup** on **timeslot 1**. |
| **TGID_TS2_ACL** | ACL for **talkgroup** on **timeslot 2**. |
| **GEN_STAT_BRIDGES** | If true, OpenBridge can trigger creation of **static** bridge rows for certain TGs (see [Bridges and talkgroups](bridges-and-talkgroups.md)). |
| **SERVER_ID** | Numeric server ID; stored as 4-byte value for OpenBridge / voice metadata. |
| **VALIDATE_SERVER_IDS** | If true (DMRE path), **source server** IDs may be checked against a downloaded list (`ALIASES` **SERVER_ID_**\*). |
| **URL_SECURITY** / **PORT_SECURITY** / **PASS_SECURITY** | If set, enables download of keys/password material from the security endpoint (see example comments). Empty = disabled. |
| **USERS_PASS** | Filename for per-radio password JSON (optional). |
| **HASH_ENCRYPT** | Path to encryption key for password file handling. |
### Talker Alias (`GLOBAL`)
Optional DMR Talker Alias on HBP (`DMRA` packets). Full guide: [Talker Alias](talker-alias.md).
| Key | Meaning |
|-----|---------|
| **TALKER_ALIAS** | Enable server TA inject/passthrough (`false` default). |
| **TALKER_ALIAS_MODE** | `both` (default), `passthrough`, or `inject`. |
| **TALKER_ALIAS_FORMAT** | Template, e.g. `{callsign} {fname}`. Max **29** chars (protocol limit, not YAML). |
| **TALKER_ALIAS_TEXT_FORMAT** | `utf8`, `iso8`, `7bit`, or comma list (e.g. `utf8,iso8` for Motorola + Hytera). Default `utf8`. |
---
## `SYSTEMS` — common fields
These appear mainly on **MASTER** (and often on **PEER**). OpenBridge uses a different subset.
| Key | Meaning |
|-----|---------|
| **MODE** | `MASTER`, `PEER`, or `OPENBRIDGE`. |
| **ENABLED** | If `false`, the system is skipped. |
| **IP** / **PORT** | UDP bind address for this system’s HBP or OpenBridge listener. |
| **PASSPHRASE** | Shared secret for HBP authentication (MASTER ↔ PEER). Must match between a PEER and its MASTER. |
| **USE_ACL** | Per-system ACL override when true (uses system-level `REG_ACL` / `SUB_ACL` / `TGID_TS*_ACL`). |
| **GROUP_HANGTIME** | Hang time (seconds) for group voice state. |
| **DEFAULT_UA_TIMER** | Default timeout (minutes in many places) for **user-activated** bridges. |
| **ANNOUNCEMENT_LANGUAGE** | Default language folder under `Audio/<lang>/` for prompts on this system. |
| **ALLOW_UNREG_ID** | Whether unregistered subscriber IDs are allowed (MASTER). |
---
## `SYSTEMS` — MASTER
| Key | Meaning |
|-----|---------|
| **REPEAT** | If true, received traffic can be **repeated** to other connected peers on the MASTER (typical conference behaviour). |
| **MAX_PEERS** | Maximum connected hotspots. On the **proxy target** MASTER, caps concurrent fan-in sessions. |
| **EXPORT_AMBE** | Feature flag for AMBE export (if enabled in build). |
| **SINGLE_MODE** | Affects OPTIONS / generator expansion (single-user style). |
| **VOICE_IDENT** | Enables periodic **voice ident** when conditions are met (see `IdentUseCases`). |
| **TS1_STATIC** / **TS2_STATIC** | Comma-separated static TG lists pushed via OPTIONS handling (see `options_config`). |
| **DEFAULT_REFLECTOR** | Default **reflector** number for `#` dial bridges (0 = none). |
| **OVERRIDE_IDENT_TG** | Optional TG for voice ident instead of all-call. |
| **GENERATOR** | If **> 1**, this MASTER is expanded into **`NAME-0`**, **`NAME-1`**, … with consecutive ports (see `expand_generator` in code). Legacy standalone **`adn-proxy`** used the same range; the **integrated** proxy instead uses **inject-only** **`PROXY.TARGET_SYSTEM`** (no per-hotspot UDP ports on the server). |
**MASTER** listens for PEER connections (unless it is the **inject-only** proxy target — see [Hotspot proxy](hotspot-proxy.md)); each authenticated peer is stored under **`PEERS`** at runtime.
---
## `SYSTEMS` — PEER
A **PEER** connects **outbound** to a **MASTER** and listens locally for the radio or app.
| Key | Meaning |
|-----|---------|
| **MASTER_IP** / **MASTER_PORT** | Address of the **MASTER** to register with (must match that MASTER’s `IP`/`PORT`). |
| **RADIO_ID** | This peer’s ID in HBP (4-byte). |
| **CALLSIGN**, **RX_FREQ**, **TX_FREQ**, **COLORCODE**, **LATITUDE**, … | RPT payload fields sent to the MASTER during registration (fixed widths in protocol). |
| **OPTIONS** | Byte string / options line (e.g. `TS2=9990;`) for static TG / behaviour. |
| **LOOSE** | Relaxed handling flag where applicable. |
The **echo** example (`adn-echo.example.yaml`) is a PEER that attaches to the **ECHO** MASTER: same **PASSPHRASE**, **MASTER_PORT** = ECHO’s **PORT**. See [Echo](echo.md).
---
## `SYSTEMS` — OPENBRIDGE
| Key | Meaning |
|-----|---------|
| **NETWORK_ID** | Must match the peer’s **NETWORK_ID** in OpenBridge packets. |
| **TARGET_IP** / **TARGET_PORT** | Remote OpenBridge peer (UDP). |
| **TGID_ACL** (or **TG1_ACL**) | Talkgroup ACL for OpenBridge (often `DENY:0-82,…` style ranges). |
| **RELAX_CHECKS** | Allow packets when peer socket does not match `TARGET` strictly (use with care). |
| **ENHANCED_OBP** | Enables **BCSQ** / **BCKA** and multi-path loop control — **should be `true`** for ADN Systems inter-server links (see below). |
| **PROTO_VER** | Embedded **DMRE** protocol version; **`5`** selects **DMRE / OpenBridge v5** (89-byte frame, BLAKE2b). Default in code is **5**; use **5** for new ADN deployments. |
**ADN Systems recommendation:** For every OpenBridge peer in the ADN mesh, set **`PROTO_VER: 5`** (DMRE v5) and **`ENHANCED_OBP: true`**. Align the same settings on **both** ends. Older **DMRD v1**-only peers are possible for backward compatibility but are not the recommended mode for the network.
Ingress filters and loop control: [OpenBridge protocol](../protocols/openbridge.md) (including [DMRE vs OpenBridge v5](../protocols/openbridge.md#dmre-and-openbridge-v5)) and [Special numbers — OpenBridge ingress](special-numbers.md#openbridge-ingress--group-tg-filters).
---
## `BRIDGES` (runtime)
The **bridge table** maps TG keys to routing rows. It is **in memory** for the running process.
The YAML loader does **not** load a top-level `BRIDGES:` block from `adn-server.yaml` into the router today — initial rows are created in code (e.g. **9990 / ECHO** bootstrap when an **ECHO** system exists), then **OPTIONS**, **user-activated** bridges, **static** bridges, and **OpenBridge** logic add rows over time.
For the conceptual model (ACTIVE, TS, TGID, timeouts): [Bridges and talkgroups](bridges-and-talkgroups.md).
---
## `REPORTS`
TCP report channel for **adn-monitor** (or compatible dashboards). **adn-server 2.x** speaks **report v2** only; legacy dashboards that expect **v1** need the optional [report-proxy](report-proxy.md) (separate package).
| Key | Meaning |
|-----|---------|
| **REPORT** | Enable/disable sending. |
| **REPORT_INTERVAL** | Periodic push interval (seconds). |
| **REPORT_PORT** | Local port the **server listens on** for report clients. |
| **REPORT_CLIENTS** | Comma-separated or list of allowed client IPs (see example). |
Details: [Monitoring and reports](monitoring.md). Legacy v1 monitors: [Report proxy](report-proxy.md).
---
## `PROXY` (integrated hotspot proxy)
Always started when a **`PROXY`** block is present (see `adn-server.example.yaml`). Hotspots connect to **`LISTEN_PORT`**; traffic is injected into **`TARGET_SYSTEM`**. Full guide: [Hotspot proxy](hotspot-proxy.md).
| Key | Meaning |
|-----|---------|
| **LISTEN_PORT** / **LISTEN_IP** | UDP bind for hotspot connections. |
| **TARGET_SYSTEM** | **MASTER** system name receiving injected HBP. That system becomes **inject-only** (`IP` / `PORT` removed at load). |
| **TIMEOUT** | Session idle timeout (seconds). |
| **DEBUG** / **CLIENT_INFO** | Logging verbosity. |
| **BLACK_LIST** / **IP_BLACK_LIST** | Block radio IDs or client IPs. |
Do **not** run standalone **`adn-proxy`** on the same **`LISTEN_PORT`** when the integrated proxy is enabled.
---
## `DATABASE` (MariaDB)
**Required** for typical conference-server configs: any deployment with **`PROXY`**, or at least one **`MASTER`** / **`OPENBRIDGE`** system. **Not** required for minimal **echo-only** PEER fleets (`adn-server.py --echo`).
| Key | Meaning |
|-----|---------|
| **DB_SERVER** | MariaDB/MySQL host. |
| **DB_USERNAME** / **DB_PASSWORD** | Credentials. |
| **DB_NAME** | Database name (often the same as **adn-monitor**, e.g. `hbmon`). |
| **DB_PORT** | TCP port (default **3306**). |
**Uses one shared connection pool** for:
- **Dynamic TG persistence** — table **`peer_dynamic_tgs`** (per-peer user-activated TGs across hotspot reconnects). The server **creates the table on startup** if missing (migration id **`004_peer_dynamic_tgs`**, same schema as adn-monitor).
- **Integrated self-service** — table **`Clients`** when **`SELF_SERVICE.USE_SELFSERVICE: true`**.
Startup aborts with a clear log if MariaDB is unreachable or **`DATABASE`** is incomplete. Install **`mysqlclient`** (`pip install -e ".[selfservice]"` includes it).
**Hot reload:** changing **`DATABASE`** requires a **full process restart**.
Details: [Bridges and talkgroups — dynamic TG persistence](bridges-and-talkgroups.md#dynamic-tg-persistence-mariadb).
---
## `SELF_SERVICE` (MySQL / dashboard options)
Optional; requires `pip install -e ".[selfservice]"` when **`USE_SELFSERVICE: true`**. Uses the **`DATABASE`** block above (not separate DB keys in **`SELF_SERVICE`**). PBKDF2 parameters must **match** **adn-monitor**. See [Self-service](../../monitor/self-service.md) and [Hotspot proxy](hotspot-proxy.md#self_service-keys).
| Key | Meaning |
|-----|---------|
| **USE_SELFSERVICE** | Enable MySQL-backed options sync from the dashboard (`true` / `false`). |
| **PBKDF2_SALT** / **PBKDF2_ITERATIONS** | Must match **`adn-monitor.yaml`** / password tooling. |
---
## `LOGGER`
Implemented in `infrastructure/logging_config.py` (`setup_logging`). Values are read from the **`LOGGER`** block (or overridden by `--logging` for **LOG_LEVEL** only).
| Key | Meaning |
|-----|---------|
| **ENABLED** | **`true`** (default when omitted) — normal logging. **`false`** — disable application log output (no console or file handlers; `NullHandler` only). Legacy configs without this key behave as today. |
| **LOG_HANDLERS** | Comma-separated list of handler **tokens** (whitespace around commas is fine). Each token selects outputs; you can combine several. Recognised values: **`console-timed`** or **`console`** — log to **stderr** with format `LEVEL asctime message`; **`file-timed`** or **`file`** — log to **LOG_FILE** with the same format (UTF-8). **Default** if omitted: `console-timed`. Examples: `console-timed` only; `file-timed` only; `console-timed,file-timed` for both console and file. |
| **LOG_FILE** | Path used when **`file-timed`** or **`file`** is in **LOG_HANDLERS**. If missing, the code defaults to `/dev/null`. If the path is **`/dev/null`**, file handlers are **not** attached even if listed. If the file cannot be opened (permissions, missing directory), a warning is written to stderr and logging continues without that file handler. |
| **LOG_LEVEL** | Root logger level: **`DEBUG`**, **`INFO`**, **`WARNING`**, **`ERROR`**, **`CRITICAL`** (case-insensitive; default **INFO**). Unknown names fall back to **INFO**. You can override at startup with **`python adn-server.py --logging LEVEL`** (same names). A custom **`TRACE`** level is registered for occasional `logger.trace(...)` calls; use **`DEBUG`** for verbose diagnostics in normal operation. |
| **LOG_NAME** | Name of the logger returned to the application (default **`ADN`**). Does not change the list of handlers; it selects which named logger gets the configured level. |
---
## `ALIASES`
Downloads and local files for **peer IDs**, **subscriber IDs**, **talkgroup labels**, optional **server ID list**, **checksums**, and **keys**. Used for dashboards, validation, and optional security downloads.
| Key | Meaning |
|-----|---------|
| **PATH** | Base directory for JSON/TSV/pickle files. |
| **TRY_DOWNLOAD** | Whether to fetch from URLs when stale. |
| **PEER_FILE** / **SUBSCRIBER_FILE** / **TGID_FILE** | Local filenames. |
| **\*_URL** | Remote sources for downloads. |
| **SUB_MAP_FILE** | Pickle path for **SUB_MAP** (private call routing); default name if empty. |
| **STALE_DAYS** | Refresh threshold for downloads. |
---
## `VOICE` (from `adn-voice.yaml` or inline)
Merged into `config["VOICE"]`. See [Voice, announcements, and TTS](voice-and-tts.md) and `adn-voice.example.yaml`.
---
## ACL strings
Processed by `acl_build`: `PERMIT:` or `DENY:` followed by comma-separated IDs or ranges.
Examples:
- `PERMIT:ALL` — allow all IDs in range.
- `DENY:1` — deny ID 1 only.
- `DENY:0-82,9990-9999` — deny listed ranges.
Global ACLs apply when `USE_ACL` is true; OpenBridge may use **TGID_ACL** on the OBP system.
---
## Python environment
Use the project interpreter (see workspace rules), e.g. `python3.11` from pyenv, for consistent behaviour with production.
---
## See also
- [Introduction](introduction.md) — role of the server.
- [Bridges and talkgroups](bridges-and-talkgroups.md) — `BRIDGES` semantics.
- [Special numbers](special-numbers.md) — reserved TGs and server IDs.
- [Echo](echo.md) — PEER example (echo process).
- [Hotspot proxy](hotspot-proxy.md) — integrated **`PROXY`** / **`SELF_SERVICE`**.

Powered by TurnKey Linux.