Self-Hosting Open Intercom
Open Intercom is open source, and you can run the whole thing on your own infrastructure without paying us anything. This guide covers what the system is made of, how to deploy it, the one architectural decision that becomes your responsibility when you self-host, and an honest account of what the managed option does that a self-hosted deployment does not. It is written so that you can make the build or buy decision with real numbers rather than a sales page.
Why we publish this. The reason to run software on Open Source Cloud should be that managing it yourself is not worth your time, not that leaving is difficult. If this guide talks you into self-hosting, that is a legitimate outcome, and the exit path existing is the point.
What Open Intercom is made of
Three components. Two of them are open source projects you deploy, and one is a database.
| Component | What it does | Source | Licence |
|---|---|---|---|
| Intercom Manager | The API and the web client. Manages productions, calls and participants. | Eyevinn/intercom-manager | MIT |
| Symphony Media Bridge | The selective forwarding unit. Every participant's audio passes through it; this is the part that has to be fast. | finos/SymphonyMediaBridge | Apache-2.0 |
| Database | Stores productions and call configuration. MongoDB or CouchDB. | Upstream project | Upstream |
Note which one is ours and which is not. The media bridge is a FINOS project, not an Eyevinn project. We did not write it and we do not control its roadmap, which is worth knowing before you build a production workflow on it, and is equally true whether you self-host or we host it for you.
Requirements
- A Symphony Media Bridge instance running and reachable.
- A MongoDB server or a CouchDB server.
-
A Docker engine, or Node.js v22 or later if you run from source.
The project's readme still says v18; `package.json` declares
"engines": { "node": ">=22.0.0" }and the Dockerfile builds onnode:22-alpine, so 22 is the real floor.
MongoDB v7 is the tested version. CouchDB is supported through the same connection-string setting, distinguished by scheme.
Running the Intercom Manager
The published image is all you need to get an instance up:
docker run -d -p 8000:8000 \
-e PORT=8000 \
-e SMB_ADDRESS=http://<smburl>:<smbport> \
-e DB_CONNECTION_STRING=<mongodb|http>://<host>:<port>/<db-name> \
eyevinntechnology/intercom-manager
The API documentation is then served from the instance itself at
/api/docs/, which is the authoritative reference for
anything this guide does not cover.
Configuration
| Variable | Purpose | Default |
|---|---|---|
PORT |
API port | 8000 |
SMB_ADDRESS |
address:port of the media bridge | http://localhost:8080 |
SMB_APIKEY |
API key presented to the media bridge, when it requires one | unset |
DB_CONNECTION_STRING |
MongoDB (mongodb://) or CouchDB (http://
/ https://)
|
mongodb://localhost:27017/intercom-manager |
PUBLIC_HOST |
Hostname used to generate shareable URLs | http://localhost:8000 |
CORS_ORIGIN |
Comma-separated allowed origins. CORS is disabled when unset, which breaks a frontend served from a different port. | unset |
ICE_SERVERS |
turn:user:pass@host,stun:host. See the NAT section
below.
|
unset |
WHIP_AUTH_KEY |
Bearer token required on the WHIP and WHEP ingest endpoints | unset |
OSC_ACCESS_TOKEN |
Personal Access Token used for link sharing and for renewing the
token the platform auth wall issues. It also gates
GET /api/v1/reauth, which answers 405
when the variable is unset, because the service is then not
running in an OSC context. Off OSC you will not set this.
|
unset |
ENDPOINT_IDLE_TIMEOUT_S |
Idle timeout for media bridge endpoints, seconds | 60 |
MONGODB_CONNECTION_STRING is deprecated. If you are
copying an older configuration, move it to
DB_CONNECTION_STRING.
Authentication is your job now, and this is deliberate
This is the single most important section of this guide, and the one most likely to be skipped.
Intercom Manager has no authentication layer of its own. Deploy it on a reachable address with no gateway in front of it and anyone who finds it can join your productions.
That is a design decision, not an oversight. How access is controlled is deployment-specific in most cases, so it belongs to whatever fronts the service rather than to the service itself. On Open Source Cloud the service sits behind the platform's auth wall, which authenticates every request before it reaches the API. When you self-host, that wall is the part you are replacing, and you have to replace it with something.
Practical options, in rough order of how often they are the right answer: an authenticating reverse proxy (oauth2-proxy, Authelia, or your existing SSO gateway) in front of the API; an ingress controller with authentication middleware; or placing the whole deployment on a private network reachable only over your VPN. Any of these is fine. None of them is optional.
One narrow exception exists and should not be mistaken for a general
mechanism: WHIP_AUTH_KEY guards the WHIP and WHEP ingest
endpoints with a bearer token. It protects those two endpoints only.
It is not API authentication.
If you are extending the codebase, do not add an in-process authentication layer. It conflicts with the platform auth wall and breaks existing deployments, including other people's.
NAT, STUN and TURN
WebRTC audio travels over UDP where it can. Participants behind strict
NAT or a corporate proxy need a relay, and when you self-host you
supply it through ICE_SERVERS, in the form
turn:username:password@turn.example.com,stun:stun.example.com.
If you provide no STUN server and WHIP endpoints are in use, the
service falls back to Google's public STUN server
(stun:stun.l.google.com:19302). That is a reasonable
default for a test deployment and a poor one for production, for the
obvious reason that your call setup then depends on a third party you
have no agreement with. Run your own, or use one you pay for.
Budget roughly 50 to 80 kbps per active participant for Opus audio. A twenty-person production needs roughly 1.5 Mbps uplink at the media bridge, not at each browser. The bandwidth is not the hard part; the media bridge's latency under load is.
Deploying the whole stack with Terraform
If you want the full stack (database, media bridge and intercom manager) provisioned as infrastructure-as-code rather than assembled by hand, the configuration is published:
git clone https://github.com/EyevinnOSC/terraform-examples.git
cd terraform-examples/examples/intercom
export TF_VAR_osc_pat="your-personal-access-token"
export TF_VAR_smb_api_key="your-smb-api-key"
export TF_VAR_db_admin_password="your-db-password"
terraform init
terraform plan
terraform apply
The osc_eyevinn_intercom_manager resource takes
name (lowercase letters and numbers only),
smb_url, smb_api_key, db_url,
and an optional osc_access_token. These examples target
Open Source Cloud, so they are the managed path expressed as code
rather than a self-hosting recipe. They are useful here for a
different reason: they document the exact shape of a working
deployment, which is a good template even if you are provisioning
somewhere else entirely.
What the managed option actually does
An honest list, so the comparison is on real terms rather than on which page you happen to be reading.
| Concern | Self-hosted | On Open Source Cloud |
|---|---|---|
| Licence cost | None. MIT and Apache-2.0. | None. Same software, same licences. |
| Authentication | You build and operate it. | Platform auth wall, already in front of the API. |
| Media bridge operation | You size, deploy, monitor and patch it. This is the component that determines audio quality under load. | Managed. Available as a dedicated add-on. |
| TURN relay | You run it or you buy it. |
Not publicly documented. The OSC intercom documentation directs
users to their own network administrator about STUN and TURN
when connections fail, and the published Terraform example sets
no
ICE_SERVERS, so confirm this before relying on it
either way.
|
| Upgrades | Yours to schedule, test and roll back. | Managed. |
| Support during a live show | Your own team. | Priority support from the Professional plan. |
| Leaving | Not applicable. | Same open source software, so the exit is a redeploy rather than a migration. |
The honest summary: self-hosting is straightforward to stand up and non-trivial to operate on show day. The parts that are easy are the container and the database. The parts that are not are the media bridge under load, the TURN relay for your most awkward participant, and having somebody who can fix comms at 19:55 on a Saturday.
Pre-production checklist
- The API is not reachable without authentication. Verify from outside your network, not from a machine on it.
-
PUBLIC_HOSTis set to the hostname participants actually use, or shared URLs will point somewhere useless. -
CORS_ORIGINlists every origin your frontend is served from. - A TURN server of your own is configured, and tested from a connection you do not control.
- The media bridge has been load-tested at your expected participant count, not at three people in the same office.
- Database backups exist and a restore has been rehearsed.
- Somebody is named as on-call for comms during the show, and is not the same person calling it.
Prefer not to operate it?
Same software, hosted and managed, on a Professional plan. Start a 14-day trial and compare it against what you just read.