Multi-node
One Ister deployment can span several servers ("nodes"). Typical reasons: media spread over machines in different rooms, or a beefy machine doing the transcoding for a NAS that stores the files. All nodes share one PostgreSQL database and one RabbitMQ broker; clients can talk to any node.
The concept
Every node runs the same application image with the same database/RabbitMQ settings, and differs only in:
app.ister.server.name— unique per nodeapp.ister.server.url— how clients and the other nodes reach itapp.ister.cluster.name— identical on every node- the
app.ister.disk.directories[n].*entries for the disks this node physically has
Startup validates the multi-node configuration and logs problems, so check the log of a newly joined node.
How work is routed
Most background work queues are directory-scoped: the queue name carries the directory name
(e.g. app.ister.server.transcode_requested.disk1), and each node only listens on the queues
for directories it owns. So when a client asks any node for a stream, the transcode request
lands on the node that holds the source file — no shared filesystem needed. This is also why
directory names must be unique across the cluster.
When node A transcodes for a playback session served by node B, A pushes each finished HLS
segment to B via POST /transcode/upload/{id}/{fileName}, authenticated with short-lived
node tokens that the nodes issue and refresh among themselves automatically (refreshed every
12 hours). You configure nothing for this beyond correct app.ister.server.url values — but
those URLs must be reachable node-to-node, not just from your browser.
Dedicated transcoder nodes
A node can also transcode for another node's disks without owning any media itself: give it no directories and instead list the directory names it should serve:
app.ister.transcoder.disks[0].name=server-1-disk1-tv
app.ister.transcoder.disks[1].name=server-1-disk1-movies
If app.ister.transcoder.disks is empty, it falls back to the node's own directories (the
normal single-node behaviour). Note: the source node must still be able to serve the file to the
transcoder — remote input is fetched over a tokenized download URL.
Worked example
docker-compose-nodes-local.yml in the repository runs a complete three-node cluster against
one database and broker:
- server-1 — owns six directories (shows, movies and music over two disks), VAAPI enabled
- server-2 — a second full node with its own disks
- transcoder-1 — no directories, only
app.ister.transcoder.disks[n]entries naming server-1's disks: it does server-1's transcoding
Points to copy from it: each node has its own CACHE_DIR, its own published port and a
server.url using a real LAN IP (not localhost — the other nodes must reach it), while
APP_ISTER_CLUSTER_NAME is the same everywhere.
Operational notes
- The client's cluster page (Settings → Cluster) shows every node and its health — the fastest "is everything up?" check.
- Scans, metadata and cleanup run per node for the directories it owns; you trigger
scanLibraryonce and each node picks up its share. - For the internals of cross-node transcoding, see the architecture documentation.
Where to next
- Search — one Typesense serves the whole cluster
- Maintenance — per-node caches and jobs