MongoDB got some bad press a few years back for having authentication disabled by default, which led to a lot of exposed databases getting their data deleted by bots. The bad news is that's still the default on a fresh installation. The good news is it takes about two minutes to fix.
I use MongoDB for projects where the data structure varies between records or where I'm dealing with nested/hierarchical data that would need awkward joins in a relational database. Once you've secured it properly and understand how the connection URI works, it's pleasant to work with.
This guide covers installation, enabling authentication immediately (don't skip this), creating application-specific users, configuring the firewall, and setting up automated backups.
I run MongoDB on Tencent Cloud Lighthouse. The 4 GB RAM plan handles most development and small production MongoDB workloads. For security, Lighthouse's console-level firewall lets you block MongoDB's default port (27017) at the infrastructure level — before traffic even reaches your server — which is an additional layer on top of the OS-level UFW rules. For storage-intensive use cases (like storing binary documents or large datasets), CBS cloud disk expansion lets you grow MongoDB's storage without server migration.
- Key Takeaways
MongoDB is a good fit when:
Relational databases (MySQL, PostgreSQL) are usually better for:
Install the official MongoDB Community Edition (the Ubuntu default repos contain an outdated version):
# Install required packages
sudo apt update
sudo apt install -y gnupg curl
# Add MongoDB GPG key
curl -fsSL https://www.mongodb.org/static/pgp/server-7.0.asc | \
sudo gpg -o /usr/share/keyrings/mongodb-server-7.0.gpg --dearmor
# Add MongoDB repository
echo "deb [ arch=amd64,arm64 signed-by=/usr/share/keyrings/mongodb-server-7.0.gpg ] https://repo.mongodb.org/apt/ubuntu jammy/mongodb-org/7.0 multiverse" | \
sudo tee /etc/apt/sources.list.d/mongodb-org-7.0.list
# Install MongoDB
sudo apt update
sudo apt install -y mongodb-org
# Start and enable MongoDB
sudo systemctl start mongod
sudo systemctl enable mongod
# Verify
sudo systemctl status mongod
mongod --version
MongoDB ships without authentication enabled. This means anyone who can connect to the MongoDB port can read and write all data. Always enable authentication before deploying.
Edit the MongoDB configuration:
sudo nano /etc/mongod.conf
Find the security section and enable authorization:
security:
authorization: enabled
Don't restart yet — we need to create the admin user first (with auth disabled). If you restart now, you won't be able to connect.
With auth still disabled, connect to MongoDB and create the admin user:
mongosh
// Switch to admin database
use admin
// Create admin user
db.createUser({
user: "admin",
pwd: passwordPrompt(), // Prompts for password securely
roles: [
{ role: "userAdminAnyDatabase", db: "admin" },
{ role: "readWriteAnyDatabase", db: "admin" },
{ role: "dbAdminAnyDatabase", db: "admin" }
]
})
// Verify
db.getUsers()
// Exit
exit
Now enable authentication and restart:
sudo systemctl restart mongod
Test that authentication is required:
# Should fail without credentials
mongosh --eval "db.adminCommand({listDatabases: 1})"
# Should work with credentials
mongosh -u admin -p --authenticationDatabase admin
Never use the admin user in your applications. Create a user with limited permissions per database:
mongosh -u admin -p --authenticationDatabase admin
// Create app database and user
use myapp_db
db.createUser({
user: "myapp_user",
pwd: passwordPrompt(),
roles: [
{ role: "readWrite", db: "myapp_db" }
]
})
// Verify
db.getUsers()
exit
Test the application user:
mongosh -u myapp_user -p --authenticationDatabase myapp_db
# use myapp_db
# db.test.insertOne({hello: "world"})
# db.test.find()
# exit
Connection string for your application:
mongodb://myapp_user:YOUR_PASSWORD@localhost:27017/myapp_db
MongoDB's default port is 27017. It should not be accessible from the public internet:
# Verify MongoDB is only listening on localhost
sudo netstat -tlnp | grep 27017
# Should show: 127.0.0.1:27017
# If showing 0.0.0.0:27017, update mongod.conf:
sudo nano /etc/mongod.conf
net:
port: 27017
bindIp: 127.0.0.1 # Listen on localhost only
sudo systemctl restart mongod
# UFW: MongoDB port should NOT be open publicly
# Only open if you're allowing remote access from a specific IP
# Tunnel port 27018 on your local machine to MongoDB on the server
ssh -L 27018:127.0.0.1:27017 ubuntu@YOUR_SERVER_IP -N
# Connect locally
mongosh --port 27018 -u admin -p --authenticationDatabase admin
sudo nano /etc/mongod.conf
net:
bindIp: 127.0.0.1,YOUR_IP
# Open port only for your IP
sudo ufw allow from YOUR_IP to any port 27017
sudo systemctl restart mongod
mongosh -u myapp_user -p --authenticationDatabase myapp_db
// Switch to your database
use myapp_db
// Insert a document
db.users.insertOne({
name: "Alice",
email: "alice@example.com",
createdAt: new Date()
})
// Insert multiple documents
db.users.insertMany([
{ name: "Bob", email: "bob@example.com" },
{ name: "Carol", email: "carol@example.com" }
])
// Find documents
db.users.find() // All documents
db.users.find({ name: "Alice" }) // Filter
db.users.find({}, { name: 1, email: 1 }) // Projection (select fields)
db.users.findOne({ email: "alice@example.com" })
// Update
db.users.updateOne(
{ email: "alice@example.com" },
{ $set: { name: "Alice Smith" } }
)
// Delete
db.users.deleteOne({ name: "Bob" })
db.users.deleteMany({ email: /example\.com$/ })
// Count
db.users.countDocuments()
db.users.countDocuments({ name: /^A/ })
// Index (for performance)
db.users.createIndex({ email: 1 }, { unique: true })
// Show indexes
db.users.getIndexes()
mongodump \
--uri="mongodb://myapp_user:PASSWORD@localhost:27017/myapp_db" \
--out=/backup/mongodb/$(date +%Y%m%d)
mongodump \
--uri="mongodb://admin:PASSWORD@localhost:27017" \
--authenticationDatabase admin \
--out=/backup/mongodb/$(date +%Y%m%d)
mongorestore \
--uri="mongodb://myapp_user:PASSWORD@localhost:27017/myapp_db" \
/backup/mongodb/20260420/myapp_db
nano ~/backup_mongodb.sh
#!/bin/bash
BACKUP_DIR="/backup/mongodb"
DATE=$(date +%Y%m%d_%H%M%S)
mkdir -p $BACKUP_DIR
mongodump \
--uri="mongodb://admin:YOUR_ADMIN_PASSWORD@localhost:27017" \
--authenticationDatabase admin \
--out=$BACKUP_DIR/$DATE \
--gzip
# Keep 7 days of backups
find $BACKUP_DIR -type d -mtime +7 -exec rm -rf {} + 2>/dev/null
echo "MongoDB backup complete: $DATE"
chmod +x ~/backup_mongodb.sh
# Cron: daily at 3 AM
(crontab -l; echo "0 3 * * * ~/backup_mongodb.sh >> ~/mongodb_backup.log 2>&1") | crontab -
A fresh MongoDB installation has no authentication. If you expose port 27017 without enabling auth, anyone can connect and access all your data.
This is one of the most common misconfigurations on public-facing servers. The steps in Part 2 and Part 3 fix this, but they must be done before you expose the server to traffic.
The safe order:
mongod.conf ✅Also: make sure the Lighthouse console firewall does not have port 27017 open. MongoDB should only be accessible from localhost or via SSH tunnel — not directly from the internet.
# Connect
mongosh -u USER -p --authenticationDatabase DB
# In mongosh
show dbs # List databases
use DBNAME # Switch database
show collections # List collections in current DB
db.stats() # Database statistics
db.collection.stats() # Collection statistics
# Admin operations (as admin)
use admin
db.getUsers() # List users
db.serverStatus() # Server statistics
db.currentOp() # Show running operations
# Service
sudo systemctl start|stop|restart mongod
sudo systemctl status mongod
sudo tail -f /var/log/mongodb/mongod.log
| Issue | Likely Cause | Fix |
|---|---|---|
| Connection refused | Service not running or wrong port | Check systemctl status SERVICE and verify firewall rules |
| Permission denied | Wrong file ownership or permissions | Check file ownership with ls -la and use chown/chmod to fix |
| 502 Bad Gateway | Backend service not running | Restart the backend service; check logs with journalctl -u SERVICE |
| SSL certificate error | Certificate expired or domain mismatch | Run sudo certbot renew and verify domain DNS points to server IP |
| Service not starting | Config error or missing dependency | Check logs with journalctl -u SERVICE -n 50 for specific error |
| Out of disk space | Logs or data accumulation | Run df -h to identify usage; clean logs or attach CBS storage |
| High memory usage | Too many processes or memory leak | Check with htop; consider upgrading instance plan if consistently high |
| Firewall blocking traffic | Port not open in UFW or Lighthouse console | Open port in Lighthouse console firewall AND sudo ufw allow PORT |
Do I need a separate server for MongoDB?
For most individual projects and small teams, running MongoDB on the same server as your application is practical. The zero-latency between app and database (localhost communication) is a genuine advantage. Separate database servers are warranted at significant scale.
How do I back up a MongoDB database?
Use the database's built-in dump tools for logical backups (recoverable to any host). Combine with Lighthouse snapshots for full-server point-in-time recovery. Set up automated daily cron jobs for consistent backups.
How do I connect to MongoDB remotely for development?
Use SSH tunneling: ssh -L LOCAL_PORT:localhost:DB_PORT user@server. This routes your local database client through SSH without exposing the database port to the internet.
What user permissions should database application users have?
Application users should have only the permissions they need — typically SELECT, INSERT, UPDATE, DELETE on their specific database. Never use the root/admin database account in application connection strings.
htop or your database's status commands and upgrade if you see consistent memory pressure.Set up your MongoDB server today:
👉 Tencent Cloud Lighthouse — Ubuntu VPS for MongoDB
👉 View current pricing and promotions
👉 Explore all active deals and offers