# Configuration All config lives in `/opt/vm-transcribe/`. Templates are committed as `*.example`; the live files are created by `install.sh` or by you. Secret-bearing files (`telegram.conf`, `contacts.conf`) are mode `640 root:asterisk` and git- ignored. Most settings can also be set via environment variables, which is how the systemd unit wires production values. Env vars override file values when both are present unless noted. --- ## Environment variables (shared) | Variable | Default | Used by | Meaning | |---|---|---|---| | `VM_DB` | `/var/lib/vm-transcribe/voicemail.db` | store, web, import | SQLite path. Created with WAL mode if missing. | | `VM_AUDIO_DIR` | `/var/lib/vm-transcribe/audio` | store, web, import | Where copied recordings live (`/.wav`). | | `VM_LOG` | `/var/log/asterisk/vm_mailcmd.log` | mailcmd | Log path. | | `VM_MODEL_CACHE` | `/opt/vm-transcribe/models` | mailcmd, import | Whisper model download/load dir. | | `VM_WHISPER_MODEL` | `base.en` | mailcmd, import | Model name. `tiny`/`base`/`small` trade speed for accuracy. | | `VM_SPOOL` | `/var/spool/asterisk/voicemail` | import | Spool root to scan. | | `VM_ASTERISK_CONF` | `/etc/asterisk/voicemail.conf` | web, auth | For PIN lookup. | --- ## voicemail.conf (Asterisk) One line is all the pipeline needs: ```ini mailcmd=/opt/vm-transcribe/venv/bin/python3 /opt/vm-transcribe/vm_mailcmd.py ``` Place it in the `[general]` section (or any context). After editing: ```bash sudo asterisk -rx 'voicemail reload' ``` `install.sh` backs up the file and adds this line automatically. --- ## telegram.conf ```ini [telegram] enabled = yes token = 123456789:AAH... ; from @BotFather default_chat_id = ; fallback for unmapped mailboxes (blank = none) send_audio = yes ; voice note with caption send_transcript = yes ; full transcript as a follow-up message timeout = 20 ; seconds per send attempt [mailbox:1001] chat_id = 123456789 ; single recipient [mailbox:1002] chat_id = 5551, 5552 ; comma list fans out to several people send_transcript = no ; any global key can be overridden per mailbox [mailbox:1003] chat_id = -1001234567890 ; negative = group chat send_audio = no ; text-only DM ``` **Routing rules** (evaluated per voicemail): 1. Match the `[mailbox:N]` section for the voicemail's mailbox number. 2. `chat_id` may be a single id, a comma-separated list (fan-out), or a group id (negative). 3. If no mailbox section matches, fall back to `default_chat_id`. 4. If `enabled = no` or no route resolves, nothing is sent — email still goes out. 5. The file is re-read on every voicemail; no reload needed after editing. **Delivery fallback chain** (per chat id, tried in order): `sendVoice` → `sendDocument` → `sendMessage` (text-only). So a Telegram outage or a bad audio file still delivers the summary. > Contact resolution note: a user must message the bot once before it can DM > them. Telegram does not permit bots to initiate conversations. --- ## contacts.conf ```ini [contacts] backends = file ; space/comma separated: file google carddav cache_ttl = 86400 ; seconds; cache hits AND misses cache_file = /var/lib/vm-transcribe/contacts-cache.json # --- 'file' backend (recommended): a vCard or CSV export ------------- [file] path = /var/lib/vm-transcribe/contacts.vcf # CSV (Google export "All contact data") is auto-detected: # path = /var/lib/vm-transcribe/contacts.csv # --- 'google' backend: People API via OAuth --------------------------- [google] token_file = /var/lib/vm-transcribe/google-token.json # Obtain a token with the People API (contacts.readonly) scope. See # docs/SECURITY.md. No app password here — OAuth only. # --- 'carddav' backend: app password, Nextcloud/Fastmail/iCloud -------- [carddav] # Google rejects app passwords (basic auth disabled 2024-09-30); a Google # URL here is refused with a log warning and the backend is skipped. url = https://contacts.fastmail.com/dav/addressbooks/user/xxx/Default username = jp@txt3.com app_password = ; app-specific password, not your login password ``` **Matching** is on the **last 9 digits** of the caller ID, so `+447700900123`, `07700900123` and `447700900123` all collapse to the same contact. Names resolve best-effort; on any backend error the caller ID is used as-is. --- ## Portal settings (per mailbox, in the SQLite store) These are edited from the portal's **Settings** page by each user; they are not config files. Every value defaults to `yes`. | Setting | Effect | |---|---| | `summarise` | Run the summariser (if off, the raw transcript is shown). | | `telegram` | Forward new voicemails to the mailbox's Telegram route (requires telegram.conf). | | `email_notify` | Send the enriched email (if off, the message is stored but not emailed). | | `highlight` | Colour the caller chip when a name is resolved from contacts. | | `max_inbox` | Keep at most N messages; oldest beyond N are auto-deleted (0 = unlimited). | --- ## vm-portal.service Production values are passed as environment in the unit file: ```ini Environment=VM_DB=/var/lib/vm-transcribe/voicemail.db Environment=VM_AUDIO_DIR=/var/lib/vm-transcribe/audio Environment=VM_ASTERISK_CONF=/etc/asterisk/voicemail.conf Environment=VM_SESSION_HOURS=12 ``` Login hardening (in-process): | Var | Default | Meaning | |---|---|---| | `VM_MAX_FAILS` | `5` | Failed attempts per (mailbox, IP) before locking. | | `VM_LOCK_MINUTES` | `15` | Lock duration. | | `VM_SESSION_HOURS` | `12` | Session lifetime. | | `VM_INSECURE_COOKIE` | unset | Set to `1` only for plain-HTTP testing; normally cookies are `Secure`. | | `VM_BASE_PATH` | `""` | Set to e.g. `/voicemail` if the app is served under a sub-path. | > A service restart clears the in-memory lockout counters. Testing lockout will > lock you out of your own verification for `VM_LOCK_MINUTES`.