One binary. Deployed in one morning.
Strowger ships as a single strowgerd executable with no
runtime dependencies — embedded SQLite, a TOML config, a systemd unit — plus the
strowger-cli admin tool. Pick your platform below, or use the one-liner.
v1.0.0-rc7 · release candidate
Debian / Ubuntu, amd64 or arm64. Detects your architecture, downloads and checksum-verifies the binary, sets up the systemd service:
curl -fsSL https://lic.strowger.io/install.sh | sudo bash
On macOS (Apple Silicon) the same script runs without sudo: it downloads, checksum-verifies and unpacks locally, then prints the manual-run steps. Then edit the config, drop in your secrets, start the service and activate the licence — see Install below.
Every release ships a SHA256SUMS file. Verify the archive before you run it:
# fetch the checksums
curl -fsSLO https://lic.strowger.io/download/strowgerd-1.0.0-rc7-SHA256SUMS
# verify (run from the folder holding the .tar.gz)
sha256sum -c strowgerd-1.0.0-rc7-SHA256SUMS 2>/dev/null | grep OK
A detached minisign signature and its public key will be published here for the 1.0 final release; the one-line installer already refuses to install on a checksum mismatch.
# unpack
tar xzf strowgerd-1.0.0-rc7-x86_64-unknown-linux-gnu.tar.gz
cd strowgerd-1.0.0-rc7-x86_64-unknown-linux-gnu
# install strowgerd + strowger-cli + systemd unit (idempotent)
sudo ./deploy/install.sh ./strowgerd
# configure: trunk, model key, inbound routes
sudo editor /etc/strowger/config.toml
sudo editor /etc/strowger/strowger.env # secrets, 0640 root:strowger
# start
sudo systemctl enable --now strowger
# activate the licence (the binary is enforced: new calls are refused until you do).
# demo self-service — light identification, 1 channel / 60-second calls:
strowger-cli register --company "Your Co" --contact "You" \
--email [email protected] --phone +33XXXXXXXXX
# commercial key instead: strowger-cli register --key <YOUR-KEY>
journalctl -u strowger -f
macOS (evaluation): unpack the darwin tarball, then run
STROWGER_CONFIG=./config.toml ./strowgerd by hand — no systemd, no root.
Production targets Linux.
Hairpin transfer latency & audio purge. Fixed accumulated latency during hairpin call transfers. Bridge audio buffers are now purged upon entering the bridged state to prevent stale pre-transfer conversational audio from playing out to the transferee, and the relay playout buffer is optimized (40ms target playout delay, 120ms maximum buffer depth).
Playout metrics. Added Prometheus metrics for monitoring playout buffer health: strowger_playout_underruns_total, strowger_playout_overruns_total, and strowger_playout_buffer_depth_samples.
Gemini 3.8 Live, qualified. The standard gemini-3.8-live model passed eight scenarios using the live Google API through Strowger's voice backend and local G.711 RTP: greeting, French caller audio, interruption, delayed tools, tool timeout, hangup, transfer signalling and silence handling.
Select it per call with "backend": "gemini", "model": "gemini-3.8-live", or set model = "gemini-3.8-live" in your existing [ai.gemini] configuration. Existing installations keep their selected model; the compiled default remains gemini-3.1-flash-live-preview.
RC6 also makes configuration tests and tests of the licence API independent of the build environment, and updates the documentation for choosing a model.
Extended Thinking and GPT-Live require further integration and are not included as supported backends. Configure Gemini 3.8 Live →
Agent call transfer, fixed. In rc4 the [transfer] section was validated but never applied, so
transfer_call was never offered to the model. rc5 wires it end to end, logs the tools declared to the
model at session setup (session configured … tools=[…]) and warns when transfer_call is
requested while transfers are disabled.
Number rewriting. An allow entry can now be a rule that rewrites the number actually dialled —
e.g. to reach a GSM gateway that selects its port by prefix. The first matching entry wins; the rewritten number is
dialled as-is.
# /etc/strowger/config.toml
[transfer]
enabled = true
mode = "hairpin" # "refer" (SIP REFER) or "hairpin" (strowger places and bridges the 2nd leg)
max_per_call = 1
allow = [
"+33*", # dialled in the trunk's usual format
{ match = "+2305*", strip = "+230", prefix = "91", trunk = "gsm" }, # +230 5763 2985 -> 9157632985 on trunk "gsm"
{ match = "5???????", prefix = "91", trunk = "gsm" }, # "5763 2985" (no country code) -> same
]
deny = ["+33899*", "+230999*"]
- Patterns: exact numbers (
+23057632985,9157632985), prefixes (+2305*,91*),?for one digit (5???????), SIP URIs,user@domain,*@domain. Requested numbers are normalised first (spaces, dashes,tel:,00…=+…). - Hardened deny: checked on the requested destination and on the rewritten number; number patterns in
denyalso cover the user part of SIP URIs (case,%2B, passwords, separators). - Breaking: a number pattern in
allowno longer accepts a SIP URI (+33*no longer allowssip:+33…@any-host); in hairpin mode everyallowentry must be a number pattern; rewrite rules are hairpin-only and are fully validated at startup (unknown fields, undeclared trunk, empty result). - Hairpin trunk selection: the second leg of an inbound call leaves on the rule's
trunk, else[transfer].hairpin_trunk, else the trunk of the matching inbound route — never a random one.
RTP ports held by another process (e.g. Syncthing on UDP 22000) are now skipped instead of failing the call.
Call payload validation limits are configurable via the [limits.payload] section in TOML or environment variables (priority: TOML > Environment > Compiled defaults):
# /etc/strowger/config.toml
[limits.payload]
objectives-len = 8192 # Max system prompt size in bytes (default: 8192)
first-message-len = 4096 # Max opening message size in bytes (default: 4096)
url-len = 2048 # Max callback_url / proxy_url length (default: 2048)
short-field-len = 256 # Max caller_id / agent_id / model / language length (default: 256)
proxy-tools = 256 # Max proxy_tools entries (default: 256)
Or set via environment variables in /etc/strowger/strowger.env:
STROWGER_MAX_OBJECTIVES_LEN, STROWGER_MAX_FIRST_MESSAGE_LEN,
STROWGER_MAX_URL_LEN, STROWGER_MAX_SHORT_FIELD_LEN, and STROWGER_MAX_PROXY_TOOLS.
Strowger is licensed per concurrent channel — one channel = one simultaneous
call. The shipped binary enforces the licence: each install carries an
offline signed licence (Ed25519) that is the sole authority and keeps working even
if the licence server is unreachable, up to its own expiry. Capacities
(max_concurrent_calls, trunks, recording, AI) are read from the verified
licence. On expiry only new calls are refused; calls in progress always finish, and
/health turns degraded with a clear reason.
Every install runs a free demo — capped at 1 trunk, 1 channel and
a 1-minute maximum call duration. Activate it once with
strowger-cli register; upgrade the same licence to lift the caps, no reinstall.
Model tokens and telecom minutes are always yours, paid at cost to your providers, with no
markup from us. See pricing.