Customizing Docker Services
Broadcast servers run three Docker services (the application, the background
job worker, and PostgreSQL) defined in /opt/broadcast/docker-compose.yml.
If you need to adjust how they run (a port binding, an environment variable,
a resource limit), do it through an override file, never by editing
Broadcast’s own files.
Warning
Never edit docker-compose.yml or any other file that ships with Broadcast.
Local modifications block the nightly script update and cause upgrades to be
refused with an error naming the modified files. Your customizations belong
in docker-compose.override.yml, which is yours alone and survives every
update.
The override file
Create /opt/broadcast/docker-compose.override.yml. Docker Compose merges it
on top of the stock docker-compose.yml automatically whenever the
services start: you express only your changes, and you keep receiving every
stock configuration improvement Broadcast ships.
Changes take effect on the next restart:
cd /opt/broadcast
./broadcast.sh restart
Examples
Setting or overriding a single value needs no special syntax: your value simply replaces the stock one:
services: app: environment: SOME_SETTING: "value"
Replacing an entry in a list (like a port binding) needs the
!override YAML tag, because Compose merges lists additively by default
(without the tag you would get the stock entry and yours):
services: postgres: ports: !override - "127.0.0.1:5432:5432"
The !override tag requires Docker Compose v2.24 or newer, which every
supported Broadcast installation ships.
Complete override files
Each file below is a whole /opt/broadcast/docker-compose.override.yml. Use one, or combine their services: entries into one file. After you save it, run ./broadcast.sh restart from /opt/broadcast.
To see the merged result before you restart, run:
cd /opt/broadcast sudo docker compose config
Move PostgreSQL to another host port
The stock file publishes PostgreSQL on 127.0.0.1:5432. If the server already runs its own PostgreSQL on 5432, the postgres container cannot take that port. This override publishes it on 5433 instead, still on the loopback interface only:
services: postgres: ports: !override - "127.0.0.1:5433:5432"
Only the host side changes. The app and job containers reach the database over the internal Docker network at postgres:5432, so they need no change. Your own tools on the server now connect to localhost:5433, and an SSH tunnel becomes ssh -L 5432:localhost:5433 root@your-server.
Use an external PostgreSQL server
The app and job containers read their database connection from three variables in /opt/broadcast/app/.env: DATABASE_HOST, DATABASE_USERNAME and DATABASE_PASSWORD. Only the broadcast user and root can read this file, so use sudo to open it. To point them at another server, put the new values in a separate file, /opt/broadcast/app/database.env:
DATABASE_HOST=db.example.internal DATABASE_USERNAME=broadcast DATABASE_PASSWORD=your-database-password
Then load that file after the stock one:
services: app: env_file: - /opt/broadcast/app/database.env job: env_file: - /opt/broadcast/app/database.env
Compose appends this env_file entry to the stock list, and a value from a later file wins, so the three variables replace the stock ones. The password stays out of the override file, which ./broadcast.sh diagnose prints in full.
Before you restart, check these points:
- Broadcast uses three databases:
broadcast_primary_production,broadcast_queue_productionandbroadcast_cable_production. Create them on the external server, or give the user permission to create databases. - Broadcast connects on the standard PostgreSQL port, 5432. If the external server listens on another port, add
PGPORTtodatabase.env, for examplePGPORT=6543. Broadcast’s database settings have no port option of their own, so the PostgreSQL client library reads the port fromPGPORT. - Use PostgreSQL 17, the version the stock
postgresservice runs. See System requirements. - Move your data first. A restart against an empty external server starts a new, empty installation. See Backup & Recovery.
Warning
The postgres container keeps running, and the management scripts still talk to it, not to your external server. ./broadcast.sh backup_database and ./broadcast.sh restore dump and load the database in the local container. The upgrade preflight, which stops an upgrade while a broadcast is sending, reads the local container too. With an external database, back it up yourself, and do not start an upgrade while a send is in progress.
Give PostgreSQL more memory
The stock services have no memory limits, so each container can already use all of the server’s RAM. What limits PostgreSQL is its own configuration. To let it cache more data, raise shared_buffers. Compose replaces the command list as a whole, so repeat the stock flag next to your new one:
services: postgres: command: - postgres - -c - idle_in_transaction_session_timeout=10min - -c - shared_buffers=1GB
1GB is an example. Size it to the RAM the server has left after the app and job containers; see Performance Tuning for how much each process uses. To confirm the value after the restart:
docker exec postgres psql -U broadcast -c "SHOW shared_buffers;"
To set more than one PostgreSQL flag, for example max_connections as well, put all of them in the same command list.
Remote database access
If you were about to expose PostgreSQL publicly, use an SSH tunnel instead, it needs no compose changes, no firewall rules, and no publicly reachable database port:
ssh -L 5432:localhost:5432 root@your-server # then connect your local tools to localhost:5432
Warning
Avoid binding PostgreSQL to a public interface or opening port 5432 in the firewall. A database exposed to the internet is one weak password away from a breach; the tunnel gives you the same access with none of the exposure.
If you already edited docker-compose.yml
A server with hand-edited Broadcast files refuses script updates and upgrades until the edits are cleared:
- Copy your changes into
/opt/broadcast/docker-compose.override.yml(remember the!overridetag when replacing list entries). - Discard the edits to Broadcast’s files:
git -C /opt/broadcast checkout -- .
- Confirm updates flow again and apply your override:
cd /opt/broadcast
./broadcast.sh update
./broadcast.sh restart
Troubleshooting
“local modifications in /opt/broadcast are blocking script updates”
Error: local modifications in /opt/broadcast are blocking script updates:
The lines after it name each modified file.
Cause: a file that ships with Broadcast was edited on the server, usually docker-compose.yml. The update refuses to pull over it.
Fix: follow If you already edited docker-compose.yml.
The override has no effect, or only half of it
Cause: one of three things:
- The services have not restarted since you saved the file.
- A list was merged instead of replaced. Without
!override, a port entry is added next to the stock one, so PostgreSQL is published on both5432and your new port. - The file is not at
/opt/broadcast/docker-compose.override.yml, or its name is different.
Fix: run sudo docker compose config in /opt/broadcast and read the merged service. If your value is missing, check the file name and path. If you see both the stock entry and yours, add !override. Then run ./broadcast.sh restart.
Good to know
- The override file is reported by
./broadcast.sh diagnose, so support can see your customizations when helping you troubleshoot. - Upgrades and restarts leave the file untouched: it is yours.
- See the CLI Reference for the commands used above, and Upgrading for what happens during an upgrade.