Install on Ubuntu 24.04 (VM)
The VM installer sets up a single-node MonoPbx on Ubuntu 24.04 LTS (amd64 or arm64) and nothing else: no Debian, no RHEL. Under the hood it is the Docker Compose production bundle. The installer adds Docker, the secrets, HTTPS, a systemd unit and a self-test around it.
:::warning Placeholder download domain
The one-line command uses get.mpbx.ilinaia.com. That domain is a placeholder: no DNS record exists and no release has been published. Until it does, build the bundle yourself (see "Building the bundle") and run the installer with MPBX_BUNDLE_FILE and MPBX_BUNDLE_SHA256 set.
:::
# once the download domain exists
curl -fsSL https://get.mpbx.ilinaia.com/install.sh | sudo bash
# today, with a bundle you built
MPBX_BUNDLE_FILE=/path/mpbx-bundle.tar.gz MPBX_BUNDLE_SHA256=<sha256> sudo -E bash install.sh
For most servers the apt package is simpler: it ships this installer and its bundle, and adds Caddy (--front caddy: HTTPS, wss://<domain>/sip, SIP over TLS on 5061).
Never run the installer on a workstation. It refuses anything that is not Ubuntu 24.04, but it still installs packages and writes to /etc and /opt. Try it in a disposable VM first.
:::note Verification status
The installer's own tests run from deploy/installer/test. A full install on a disposable Ubuntu 24.04 VM is the owner's manual check (pending). The guide's runnable blocks are checked by site/scripts/check-guides.mjs.
:::
What it does
| Step | Detail |
|---|---|
| Preflight | Ubuntu 24.04, x86_64 or aarch64, systemd, root, 2 CPUs, 4 GB RAM, 20 GiB free under /var/lib, ports 80 and 443 and the web port free, a terminal (to confirm the recovery key), the public IP, and DNS of --domain pointing at that IP. |
| Docker | Skipped if Docker Engine 24+ with Compose 2.24+ already works. Otherwise Docker's official apt repository, and the signing-key fingerprint must match the one pinned in the script or nothing is installed. |
| Bundle | Downloads mpbx-bundle.tar.gz and SHA256SUMS, verifies the SHA-256 and installs to /opt/mpbx. |
| Secrets | Runs mpbx init. On a terminal it shows the recovery key once and asks you to re-type one group of it before anything is written. It also prints the single-use setup URL for the first administrator. |
| Service | /etc/systemd/system/mpbx.service (enabled) and the /usr/local/sbin/mpbx-ctl helper. |
| Self-test | mpbx-ctl selftest checks the unit, every container, the API over HTTP and HTTPS, that no database port listens on the host, and that .env is mode 0600. |
| Firewall | Prints the rules to open. It changes no firewall. |
Options
--domain FQDN public name (its A record must point at this server); with --accept-acme-terms enables ACME
--accept-acme-terms accept the ACME CA's subscriber agreement (Let's Encrypt by default)
--acme-email ADDRESS contact for the CA's expiry notices
--acme-directory URL another ACME CA (https only)
--public-ip IP skip the public-IP lookup
--no-tls | --tls do not publish 80/443 | publish them (default)
--http-port PORT plain web/API port (default 8080)
--channel stable|beta|nightly, --version X
--unattended no terminal: the recovery key is printed once to stdout and cannot be confirmed
--yes do not ask "Continue?"
--front caddy puts Caddy on 80/443 in front of mpbx (wss /sip for the web softphone, SIP over TLS on 5061; without --domain the name is <public-ip>.sslip.io), --no-acme never uses ACME, --relay-url URL and --no-relay choose the push relay. --skip-dns-check, --force-bundle, --skip-resource-checks and --docker-only also exist.
Firewall
| Port | Why |
|---|---|
| 80/tcp, 443/tcp | ACME challenge and redirect; web client, API and WebSocket |
| 5060/udp+tcp, 5061/tcp | SIP. The SIP edge role is not available yet, so nothing listens here today. |
| 30000-40000/udp | RTP (rtpengine). Without it calls connect but have no audio. |
| 3478 and the relay range | only with the turn profile |
Never expose 5432, 6379, 8123, 9000 or 22222 (rtpengine's control port has no authentication). The bundle publishes none of them. Docker-published ports bypass ufw.
Day-to-day commands
sudo mpbx-ctl status
sudo mpbx-ctl logs mpbx
sudo mpbx-ctl selftest
sudo mpbx-ctl restart
sudo mpbx-ctl stop
sudo mpbx-ctl setup-url # a new single-use setup URL; the previous one stops working
sudo mpbx-ctl version
Settings and secrets live in /opt/mpbx/compose/prod/.env. Back this file up together with the Docker volumes (see Backup and restore).
Re-running is safe
Every step converges. Existing secrets are never regenerated, .env values you changed are kept, and nothing is deleted. A failed install can be started again. Upgrade and rollback (mpbx upgrade) are not built yet: a bundle of a different version is refused unless you pass --force-bundle.
Uninstall
sudo mpbx-ctl uninstall # asks first; keeps the Docker volumes and .env
sudo mpbx-ctl uninstall --delete-data # also deletes the volumes and /opt/mpbx; you must type this host's name
--yes alone never deletes data. Docker, its apt source and your firewall are never touched. Deleting data also deletes the master key: without a backup and its passphrase it cannot be recovered.
Building the bundle
From a checkout of the repository, run deploy/installer/build-bundle.sh --version X.Y.Z --images-file images.env --out dist. It produces mpbx-bundle.tar.gz and SHA256SUMS. images.env sets MPBX_IMAGE and MPBX_RTPENGINE_IMAGE. There is no bundle or image signing in v1: integrity rests on HTTPS to the download host, the SHA-256 of the bundle, the pinned Docker key and digest-pinned images.