本技术文档提供英文版本。
Sentinel ID stores people, vehicles, cases, templates, sightings and the audit log in Oracle Database or MongoDB, chosen by the agency. This page installs MongoDB; Oracle is at the end. At national scale MongoDB runs as a sharded cluster: config servers hold the cluster metadata, shards hold the data (each a 3-member replica set), and mongos routers on the application servers send each query to the right shard.
For the reference size: 3 config servers, 24 shards × 3 members. A pilot can start with one 3-member replica set and be converted to a sharded cluster later.
Install MongoDB (every database server)
curl -fsSL https://www.mongodb.org/static/pgp/server-8.0.asc | sudo gpg -o /usr/share/keyrings/mongodb-server-8.0.gpg --dearmor
echo "deb [ signed-by=/usr/share/keyrings/mongodb-server-8.0.gpg ] https://repo.mongodb.org/apt/ubuntu noble/mongodb-org/8.0 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-8.0.list
sudo apt update && sudo apt install -y mongodb-org
Use XFS for the data volume, mounted with noatime, and disable Transparent Huge Pages as MongoDB recommends.
Security first: TLS and member authentication
Every member authenticates to the others with its x.509 certificate from the internal CA, and all traffic is TLS:
# /etc/mongod.conf (common part)
net:
port: 27018
bindIp: 10.40.1.21 # this server's data-zone address only
tls:
mode: requireTLS
certificateKeyFile: /etc/mongodb/tls/server.pem
CAFile: /etc/mongodb/tls/ca.pem
security:
authorization: enabled
clusterAuthMode: x509
storage:
dbPath: /data/mongodb
wiredTiger:
engineConfig:
cacheSizeGB: 180 # about 70% of RAM on a 256 GB server
systemLog:
destination: file
path: /var/log/mongodb/mongod.log
logAppend: true
Config servers (3 servers)
Add to /etc/mongod.conf:
sharding:
clusterRole: configsvr
replication:
replSetName: cfg
Start them and initiate the replica set from one of them:
rs.initiate({ _id: "cfg", configsvr: true, members: [
{ _id: 0, host: "db-cfg-a.data.internal:27019" },
{ _id: 1, host: "db-cfg-b.data.internal:27019" },
{ _id: 2, host: "db-cfg-c.data.internal:27019" } ] })
Shards (24 replica sets of 3)
On each member of shard 12, for example:
sharding:
clusterRole: shardsvr
replication:
replSetName: s12
Initiate each shard's replica set the same way (rs.initiate with its three members). Place the three members of a shard in different racks or power domains.
Routers (mongos) on application and ingest servers
Run one mongos per application and ingest server, listening on 127.0.0.1 only, so the application connects locally:
# /etc/mongos.conf
sharding:
configDB: cfg/db-cfg-a.data.internal:27019,db-cfg-b.data.internal:27019,db-cfg-c.data.internal:27019
net:
port: 27017
bindIp: 127.0.0.1
tls:
mode: requireTLS
certificateKeyFile: /etc/mongodb/tls/client.pem
CAFile: /etc/mongodb/tls/ca.pem
Create a systemd unit mongos.service that runs /usr/bin/mongos --config /etc/mongos.conf as the mongodb user.
Add the shards and shard the collections
From any mongos, as the cluster administrator:
sh.addShard("s01/db-s01-a.data.internal:27018,db-s01-b.data.internal:27018,db-s01-c.data.internal:27018")
// ... repeat for s02 to s24
sh.enableSharding("sentinel_id")
sh.shardCollection("sentinel_id.fingerprinttemplates", { _id: "hashed" })
sh.shardCollection("sentinel_id.facetemplates", { _id: "hashed" })
sh.shardCollection("sentinel_id.people", { _id: "hashed" })
sh.shardCollection("sentinel_id.vehicles", { _id: "hashed" })
sh.shardCollection("sentinel_id.sightings", { cameraId: 1, capturedAt: 1 })
sh.shardCollection("sentinel_id.events", { _id: "hashed" })
Application user
Create a least-privilege user for Sentinel ID (read and write on its database only), plus a separate read-only user for reporting and a backup user:
db.getSiblingDB("admin").createUser({ user: "sentinel_app", pwd: passwordPrompt(), roles: [ { role: "readWrite", db: "sentinel_id" } ] })
The application's connection string is then:
MONGO_URI=mongodb://sentinel_app:<password>@127.0.0.1:27017/sentinel_id?authSource=admin&tls=true
Encryption at rest
Use encrypted disks (LUKS2, see Prerequisites) on every member. Where your MongoDB edition supports the encrypted storage engine, enable it as well, with keys held in the agency KMS over KMIP.
Firewall rules (data zone)
27018(shards) and27019(config) from the application, ingest and matcher zones and from the other members only.- SSH from the bastion only. Nothing from the edge zone.
Oracle instead of MongoDB
Agencies that standardise on Oracle run Sentinel ID on Oracle Database 23ai / 26ai. Set DB_TYPE=oracle and ORACLE_URI, and copy existing data with npm run db:copy. Partitioning, RAC and Data Guard then provide the scale-out and recovery described above.
Next: Install the application tier.