All are built with
CGO_ENABLED=0, so they copy onto a machine and run.
Prerequisites
- PostgreSQL 14 or later
- Redis, on loopback
- FreeSWITCH, on the node
ffmpeg, for media conversion
Bringing it up
1
Database
Create the role and database, then set
FIRETONE_DATABASE_URL.2
Build
3
Migrate
4
Run
deploy/.5
The node
Build and configure FreeSWITCH from
deploy/node/, then point it at the
control plane’s ESL listener.The daemon refuses to start if
These are deliberate refusals, not crashes:FIRETONE_DATABASE_URL,FIRETONE_JWT_SECRETorFIRETONE_PROVISION_SECRETis missing.- The ESL, provisioning or media-stream listener is bound to
0.0.0.0. Those three serve SIP passwords and raw call audio; a wildcard bind is not a configuration choice it will accept.
Three that disable a feature rather than stopping the daemon
- Without
FIRETONE_SECRET_KEY, provider credentials cannot be stored and virtual agents fall back to an echo provider. - Without
FIRETONE_PIN_PEPPER, agent PIN sign-in is disabled entirely rather than hashing without a pepper. - Without
FIRETONE_FS_CONF_DIR, the daemon provisions no switch: a register-mode trunk never registers and the carriers ACL is never written, so adding an address under a trunk changes the database and nothing else. The trunk’s page says so; nothing else will.
The unit must also be able to write there.
install-service.sh reads that
variable and adds the generated directories to ReadWritePaths —
ProtectSystem=strict makes everything else read-only whatever the ownership
says, and the symptom is a “read-only file system” error that looks like a
disk fault.SIP-TLS for desk phones
A phone outside the office should register over TLS on 5061; on 5060 its password exchange and audio cross the internet in the clear. The switch config step turns TLS on by itself whenever it finds a certificate a phone could trust, and decides again on every run, so an update cannot switch it off:sip-tls.pemin the secrets directory — key, certificate and chain in one file; or- a real certificate for the host installed as
wss.pem(the self-signed one a proxied box generates for itself does not count).
sip.<domain> and install
it as sip-tls.pem. SIP and media are IPv4 only.
FT_SIP_TLS=1 insists and refuses to continue without one; FT_SIP_TLS=0 keeps
it off. SIP_TLS_VERSION defaults to tlsv1.2,tlsv1.3. Every refusal happens
before the running configuration is touched. Open 5061/tcp in the cloud
security group; the host firewall rule is installed for you.
Where the switch reaches the control plane
The switch connects to firetoned for every call (ESL) and every registration (the directory). Both addresses are read from firetoned’s ownFIRETONE_ESL_LISTEN and FIRETONE_PROVISION_LISTEN when the switch config
step runs, so the two ends agree. For a switch on another machine set
FIRETONE_CONTROL_HOST to the control plane’s mesh address — ESL is plaintext,
so never a public one.
Behind a reverse proxy
SetFIRETONE_TRUSTED_PROXIES. Without it every request appears to come from
the proxy, and per-IP rate limits collapse onto one address — which means they
protect nothing.
Two commands worth knowing
The environment file is0600 and owned by the service user, so the obvious
hand-typed forms fail in ways that blame the wrong thing. Both are shipped:
The staging installer (
deploy/staging/install-ubuntu.sh) is run regularly
and its gaps are fixed as they are found; a first run on a genuinely clean
machine is still the less-travelled path. Expect to read the scripts as well
as run them — each explains what it refuses to do and why.