Skip to main content
Until you give it a certificate, Fonoster serves the dashboard and API over plain HTTP on port 8449, so passwords, API keys and tokens cross the network in clear text. Use this page to serve every name you use over HTTPS, and to renew the certificate without touching the machine again. Two rows. Serving: browsers and SDKs reach Envoy over HTTPS at app.example.com and api.example.com; Envoy holds the certificate and passes requests to the dashboard and API over plain HTTP inside. Renewing, from the certbot timer twice a day: a pre hook stops Envoy to free port 80, certbot renews with Let's Encrypt, and a post hook recreates Envoy, which loads the new certificate. Each renewal takes the dashboard and API offline for about 10 seconds; calls don't go through Envoy. Two rows. Serving: browsers and SDKs reach Envoy over HTTPS at app.example.com and api.example.com; Envoy holds the certificate and passes requests to the dashboard and API over plain HTTP inside. Renewing, from the certbot timer twice a day: a pre hook stops Envoy to free port 80, certbot renews with Let's Encrypt, and a post hook recreates Envoy, which loads the new certificate. Each renewal takes the dashboard and API offline for about 10 seconds; calls don't go through Envoy. Whatever tool you use, it takes three things: one certificate that covers every name, HTTPS turned on in .env, and Envoy recreated after each renewal so it loads the new files. This page does them with certbot and Let’s Encrypt. To use other tools, see Other ways.

Before you begin

You need:
  • Fonoster installed with Docker Compose. See Install with Docker Compose.
  • Every name you serve pointing at this machine, for example app.example.com for the dashboard and api.example.com for the SDKs. One name for both works too.
  • Ports 80 and 443 free on this machine and open in any firewall in front of it.
Run the commands on this page as root.

Get a certificate

1

Install certbot

Install certbot from your distribution. On Ubuntu and Debian:
The package also installs a timer that runs renewals twice a day.
2

Get one certificate for every name

Get a certificate with one -d per name. The first name also names the folder the files land in:
The certificate and key are in /etc/letsencrypt/live/app.example.com/ as fullchain.pem and privkey.pem.

Turn on HTTPS

1

Set the four lines in .env

In your fonoster folder, set these lines in .env. PUBLIC_URL is the address people open the dashboard at:
.env
2

Apply it

Write the configuration again and recreate the services:
Envoy now serves HTTPS on 443 and redirects 80 to it. Port 8449 closes, and browser calls switch to wss:// on their own.
3

Check it

Request the dashboard over HTTPS. It answers 200:

Renew automatically

The timer renews the certificate when it has 30 days left. Envoy holds port 80 and reads the certificate only when its container is created, so add two hooks: one stops Envoy before a renewal, the other recreates it after.
1

Add the hooks

Write the two hook scripts. Change /opt/fonoster if your fonoster folder is elsewhere:
2

Try a renewal

Run a renewal against Let’s Encrypt’s test servers, hooks included:
It ends with Congratulations, all simulated renewals succeeded. certbot reports the hooks’ progress lines as “error output”. They aren’t errors.
Each renewal takes the dashboard and API offline for about ten seconds. Calls in progress aren’t affected: SIP and call audio don’t go through Envoy.

Other ways

certbot can prove you own the names through your DNS provider instead of port 80, so Envoy keeps running during renewals. Install your provider’s certbot plugin, issue the certificate with it instead of --standalone, and keep only the post hook.
If a proxy already terminates TLS (Caddy, nginx, Traefik, a cloud load balancer), keep Envoy on plain HTTP on this machine only and let the proxy hold the certificate:
.env
Run init and docker compose up -d, then point the proxy at 127.0.0.1:8449. It must forward gRPC (HTTP/2) and WebSocket upgrades on /sip.
Point TLS_CERT and TLS_KEY at your PEM files: the certificate chain and the private key. After you replace them, recreate Envoy with docker compose up -d --force-recreate envoy.

SIP over TLS

SIP stays on UDP and TCP 5060. To also accept SIP over TLS on 5061, convert your certificate into a PKCS#12 keystore for Routr:
Then uncomment the routr lines in compose.tls.yaml and the tls transport in config/routr-edgeport.example.yaml, set its keyStorePassword and trustStorePassword to <password>, and run init and docker compose up -d. Carriers and softphones then use transport=tls on port 5061. Call audio isn’t encrypted by this.The keystore is a copy of the certificate, so rebuild it after each renewal: add the openssl line and docker compose up -d --force-recreate routr to the post hook.

Troubleshooting

HTTPS is on, but PUBLIC_URL still starts with http://. Set it to https:// and the certificate’s name, then run init again.
COMPOSE_FILE names compose.tls.yaml, so Compose needs both files. Check the two paths in .env exist on this machine.
TLS_CERT and TLS_KEY are set, but COMPOSE_FILE doesn’t name compose.tls.yaml. Add the COMPOSE_FILE line.
Something holds port 80, usually Envoy. Add the hooks above, or stop Envoy before you issue the first certificate.