Skip to main content

Multi-Server Deployment

The default installation runs everything on one host. When the camera count or the storage load outgrows it, spread the containers over several Linux hosts that together form one Face Matcher site: one PostgreSQL database, one RabbitMQ broker and one S3 storage, shared by all engine services. Every host runs Docker Compose from the same release package; only .env and the set of started services differ.

This page uses three hosts as an example. Firewall rules between them follow Network and ports.

HostAddressRuns
A10.11.12.1Dependencies only: PostgreSQL, RabbitMQ, SeaweedFS, pgAdmin
B10.11.12.2All single-instance services, Station, cam-1 to cam-5, workers
C10.11.12.3cam-6 to cam-10 plus extra extractor and liveness replicas

Host A: dependencies​

Create the network and start only the dependency stack. Its Compose file declares face-matcher-network as external, so the network must exist first:

docker network create face-matcher-network
docker compose -f dependencies/docker-compose.yml up -d

The dependencies publish PostgreSQL 5432, RabbitMQ 5672 (AMQP), 1883 (MQTT), 5552 (streams) and 15672 (management), S3 8333 and pgAdmin 7070 on all interfaces. Change the default credentials in dependencies/docker-compose.yml before the other hosts connect, and restrict the ports to hosts B and C. Put the pgsqldata and seaweedfsdata volumes on fast local storage; in a high-load site PostgreSQL and SeaweedFS can be split onto separate hosts by the same method.

Hosts B and C: point the services at host A​

Each host needs its own license in secrets/, because the license is tied to the host hardware ID (see Get a license). Then edit .env on both hosts so the dependency addresses point to host A instead of the container names:

RabbitMQ__Hostname=10.11.12.1
MQTT__Hostname=10.11.12.1
ConnectionStrings__CoreDbContext=Server=10.11.12.1;Database=facematcher;Username=postgres;Password=<password>;Trust Server Certificate=true;
S3Bucket__Endpoint=http://10.11.12.1:8333

Host B runs the full stack. Set CameraServicesCount to the total number of cameras in the site (10 in this example), set S3_ENDPOINT=http://10.11.12.1:8333 in .env.station, export STATION_PUBLIC_HOST=10.11.12.1 so that the image links Station hands to browsers point at host A, and run ./start.sh. The script runs the database migration against host A and starts every service. Add CAM_PREVIEW_HOST_SFCAM6=10.11.12.3 and so on to .env.station for the cameras hosted elsewhere.

Host C runs camera containers and workers only. Add cam-6 to cam-10 to its docker-compose.yml as described in Scaling (service names SFCam6 to SFCam10, preview ports 30006 to 30010), remove the services this host must not run (base, api, graphql-api, streamdatadbworker, the face search service, matcher, edge-*, db-synchronization-* and cam-1 to cam-5), and start without start.sh, which would run the migration and the whole stack:

ln -s secrets/iengine.lic iengine.lic
docker network create face-matcher-network
docker compose up -d

Workers on host C (extractor, liveness, detector) consume the same RabbitMQ queues as those on host B, so they add capacity to the whole site.

The shared network is per host​

face-matcher-network is a Docker bridge network that exists separately on every host. Names such as pgsql, rmq, seaweedfs and api resolve only among containers on the same host, which is why .env on hosts B and C uses addresses. Two consequences follow:

  • RabbitMQ advertises its stream endpoint under the name rmq (advertised_host rmq in dependencies/docker-compose.yml). Services that use streams on port 5552 (edge-streams-state-synchronizer, db-synchronization-leader, db-synchronization-follower) must be able to resolve that name from their host. Add extra_hosts: ["rmq:10.11.12.1"] to those services in docker-compose.override.yml, or change the advertised host on host A to its address.
  • A stack built on Face Matcher, such as Smart Corridor, joins face-matcher-network on the host that runs api and graphql-api (host B), and reaches the dependencies at the addresses in .env. See Deployment topologies for the supported layouts.