High-availability MongoDB cluster across 4x Raspberry Pi 3 Model B nodes, tuned for 1GB RAM and 100Mbps Ethernet.
┌─────────────────────────────────────────────────────────┐
│ MongoDB Replica Set │
│ │
│ Node 1 (192.168.1.101) ── Primary ⭐ │
│ Node 2 (192.168.1.102) ── Secondary │
│ Node 3 (192.168.1.103) ── Secondary │
│ Node 4 (192.168.1.104) ── Arbiter ⚖️ (or Secondary) │
└─────────────────────────────────────────────────────────┘
Connection String:
mongodb://192.168.1.101:27017,192.168.1.102:27017,192.168.1.103:27017/?replicaSet=rs0
- 4x Raspberry Pi 3 Model B (1GB RAM)
- Raspberry Pi OS 64-bit (Debian Bookworm) - required for ARM64 MongoDB
- SSH access to all nodes
- Static IPs assigned to each node
- External SSD recommended (better IOPS than SD cards)
On each Pi, ensure you're running 64-bit OS:
uname -m # Should return: aarch64If not, flash Raspberry Pi OS 64-bit to your SD card/SSD.
Set environment variables on the machine where you'll run scripts:
export NODE1_IP="192.168.1.101"
export NODE2_IP="192.168.1.102"
export NODE3_IP="192.168.1.103"
export NODE4_IP="192.168.1.104"
export REPLICA_SET_NAME="rs0"Copy the scripts and config to each node, then run:
# On Node 1
NODE_IP=192.168.1.101 sudo -E bash scripts/install-mongodb.sh
# On Node 2
NODE_IP=192.168.1.102 sudo -E bash scripts/install-mongodb.sh
# On Node 3
NODE_IP=192.168.1.103 sudo -E bash scripts/install-mongodb.sh
# On Node 4
NODE_IP=192.168.1.104 sudo -E bash scripts/install-mongodb.shOr use SSH to automate:
for i in 1 2 3 4; do
NODE_IP="192.168.1.10${i}" \
ssh pi@"192.168.1.10${i}" \
'bash -s' < scripts/install-mongodb.sh
doneRun this ONCE on Node 1 (the node you want as primary):
bash scripts/init-replica-set.shThis will:
- Verify connectivity to all nodes
- Initialize the replica set configuration
- Wait for primary election
- Apply performance tuning
bash scripts/cluster-health.shFor continuous monitoring:
bash scripts/cluster-health.sh --watchIf you prefer to set up manually without scripts:
# Install MongoDB
curl -fsSL https://www.mongodb.org/static/pgp/server-7.0.asc | \
sudo gpg --dearmor -o /usr/share/keyrings/mongodb-server-7.0.gpg
echo "deb [signed-by=/usr/share/keyrings/mongodb-server-7.0.gpg arch=arm64] https://repo.mongodb.org/apt/debian bookworm/mongodb-org/7.0 main" | \
sudo tee /etc/apt/sources.list.d/mongodb-org-7.0.list
sudo apt update
sudo apt install -y mongodb-org
# Create tuned config (replace 192.168.1.101 with each node's IP)
sudo tee /etc/mongod.conf << 'EOF'
storage:
dbPath: /var/lib/mongodb
wiredTiger:
engineConfig:
cacheSizeGB: 0.25
journalCompressor: snappy
collectionConfig:
blockCompressor: snappy
indexConfig:
prefixCompression: true
systemLog:
destination: file
path: "/var/log/mongodb/mongod.log"
logAppend: true
net:
port: 27017
bindIp: 192.168.1.101,127.0.0.1 # CHANGE THIS
maxIncomingConnections: 100
replication:
replSetName: "rs0"
oplogSizeMB: 512
processManagement:
fork: false
timeZoneInfo: /usr/share/zoneinfo
EOF
sudo systemctl enable mongod
sudo systemctl start mongodmongosh --eval '
rs.initiate({
_id: "rs0",
members: [
{ _id: 0, host: "192.168.1.101:27017", priority: 3 },
{ _id: 1, host: "192.168.1.102:27017", priority: 2 },
{ _id: 2, host: "192.168.1.103:27017", priority: 1 },
{ _id: 3, host: "192.168.1.104:27017", arbiterOnly: true }
]
})
'Apply memory limits and security restrictions:
sudo systemctl edit mongod
# Paste contents of: systemd/mongod.override.conf
sudo systemctl daemon-reload
sudo systemctl restart mongodThe configuration is already tuned for Pi 3B:
| Setting | Value | Reason |
|---|---|---|
cacheSizeGB |
0.25 | Leaves room for OS + other processes |
oplogSizeMB |
512 | Enough for low-write workloads |
maxIncomingConnections |
100 | Prevents connection overload |
MemoryMax |
700MB | Hard limit to prevent OOM |
CPUQuota |
80% | Prevents thermal throttling |
- Use external SSD: Dramatically improves I/O performance
- Disable swap:
sudo dphys-swapfile swapoff && sudo systemctl disable dphys-swapfile - Set CPU governor:
echo "performance" | sudo tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor - Monitor temperature:
vcgencmd measure_temp- throttle if > 80°C
const mongoose = require('mongoose');
mongoose.connect(
'mongodb://192.168.1.101:27017,192.168.1.102:27017,192.168.1.103:27017/myapp?replicaSet=rs0',
{
readPreference: 'secondaryPreferred', // Read from secondaries when possible
maxPoolSize: 10, // Keep connections low for 100Mbps
}
);from pymongo import MongoClient
client = MongoClient(
'mongodb://192.168.1.101:27017,192.168.1.102:27017,192.168.1.103:27017/?replicaSet=rs0',
readPreference='secondaryPreferred',
maxPoolSize=10,
)
db = client['myapp']
collection = db['documents']# One-time check
bash scripts/cluster-health.sh
# Continuous watch
bash scripts/cluster-health.sh --watch# Replica set status
mongosh --eval "rs.status()"
# Replication info
mongosh --eval "rs.printReplicationInfo()"
mongosh --eval "rs.printSecondaryReplicationInfo()"
# Server status
mongosh --eval "db.serverStatus()"# Memory usage
free -h
# MongoDB process memory
ps aux | grep mongod
# Disk I/O
iostat -x 1
# Network throughput
iftop# Check logs
sudo journalctl -u mongod -f
# Check data directory permissions
ls -la /var/lib/mongodb
sudo chown -R mongodb:mongodb /var/lib/mongodb- Ensure all nodes can reach each other (firewall rules)
- Verify
/etc/mongod.confhas correctbindIpon each node - Check NTP sync across all nodes:
timedatectl
# Check oplog window
mongosh --eval "rs.printReplicationInfo()"
# If oplog is too small, increase it (on primary):
mongosh --eval "
use local
db.oplog.rs.drop()
db.adminCommand({replSetResizeOplog: 1, size: 1024})
"# Apply systemd memory limits
sudo systemctl edit mongod
# Add: MemoryMax=700M
sudo systemctl daemon-reload
sudo systemctl restart mongod
# Or reduce WiredTiger cache in /etc/mongod.conf
# storage.wiredTiger.engineConfig.cacheSizeGB: 0.2After the cluster is running, enable authentication:
# Generate keyfile
openssl rand -base64 756 > /tmp/mongodb-keyfile
chmod 400 /tmp/mongodb-keyfile
# Copy to all nodes
for ip in 101 102 103 104; do
scp /tmp/mongodb-keyfile pi@192.168.1.${ip}:/etc/mongodb-keyfile
ssh pi@192.168.1.${ip} "sudo chown mongodb:mongodb /etc/mongodb-keyfile"
done
# Create admin user (on primary, before enabling auth)
mongosh
use admin
db.createUser({
user: "admin",
pwd: "strong_password_here",
roles: [{ role: "root", db: "admin" }]
})
# Uncomment security section in /etc/mongod.conf on all nodes
# security:
# authorization: enabled
# keyFile: /etc/mongodb-keyfile
# Restart all nodes (one at a time, starting with secondaries)pg_cluster/
├── config/
│ └── mongod.conf # MongoDB configuration template
├── scripts/
│ ├── install-mongodb.sh # Automated installation
│ ├── init-replica-set.sh # Replica set initialization
│ └── cluster-health.sh # Health monitoring
├── systemd/
│ └── mongod.override.conf # Systemd resource limits
└── README.md # This file
On Raspberry Pi 3B (1GB RAM, 100Mbps Ethernet, external SSD):
| Metric | Value |
|---|---|
| Insert throughput | 200-500 docs/sec |
| Query throughput | 500-2000 queries/sec |
| Replication lag | < 100ms (typical) |
| Failover time | 10-30 seconds |
| Memory usage | ~300-500MB per node |
- Set up automated backups:
mongodumpon secondary nodes - Configure alerts for failover events
- Add application-level retry logic for failover handling
- Monitor disk growth and oplog size
MIT - Use at your own risk