Install MongoDB on a VPS: Setup, Auth & Remote Access Fixes
We get a fair number of tickets that start the same way: "I installed MongoDB on my VPS and now I can't connect from my app server" — or worse, "someone deleted my database and left a ransom note in a collection called READ_ME." Both usually trace back to the same root cause: MongoDB ships wide open by default, and most setup guides skip the part where you lock it down. Here's how to install it properly on a fresh Ubuntu VPS, turn on authentication before you do anything else, and fix the connection errors you'll hit along the way.
Installing MongoDB from the official repo
Don't use the mongodb package from Ubuntu's default repos — it's often an old, unmaintained fork. Pull the real thing from MongoDB's own APT repository instead.
sudo apt update
sudo apt install -y gnupg curl
curl -fsSL https://pgp.mongodb.com/server-7.0.asc | sudo gpg -o /usr/share/keyrings/mongodb-server-7.0.gpg --dearmor
echo "deb [signed-by=/usr/share/keyrings/mongodb-server-7.0.gpg] https://repo.mongodb.org/apt/ubuntu $(lsb_release -cs)/mongodb-org/7.0 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-7.0.list
sudo apt update
sudo apt install -y mongodb-org
Start it and make sure it survives a reboot:
sudo systemctl enable --now mongod
sudo systemctl status mongod
If lsb_release -cs returns a codename MongoDB doesn't support yet (common right after a new Ubuntu release), just hardcode the last supported one, e.g. jammy, in the repo line above.
Turn on authentication before you touch anything else
Fresh MongoDB has no auth enabled. Anyone who can reach port 27017 can read, write, and drop every database on the box. This is exactly how the mass "ransomware" wipes you've probably read about happen — bots scan the internet for open Mongo instances 24/7, and yours will get found within hours of being exposed. Fix this before you create a single collection.
First, connect locally and create an admin user:
mongosh
use admin
db.createUser({
user: "admin",
pwd: passwordPrompt(),
roles: [{ role: "userAdminAnyDatabase", db: "admin" }, "readWriteAnyDatabase"]
})
exit
Now enable auth in the config file:
sudo nano /etc/mongod.conf
security:
authorization: enabled
Restart and confirm you now need credentials:
sudo systemctl restart mongod
mongosh -u admin -p --authenticationDatabase admin
Create a separate, scoped user for each application — never point your app at the admin account:
use myapp_db
db.createUser({
user: "myapp_user",
pwd: passwordPrompt(),
roles: [{ role: "readWrite", db: "myapp_db" }]
})
Enabling remote access safely
By default, mongod only listens on 127.0.0.1, so nothing outside the server can even reach it — that's a good thing. If your app runs on a different server and genuinely needs remote access, open it up deliberately rather than binding to all interfaces.
sudo nano /etc/mongod.conf
net:
port: 27017
bindIp: 127.0.0.1,10.0.0.5
Replace 10.0.0.5 with the VPS's private or public IP, then restrict who can reach that port at the firewall level — this matters more than the bindIp line itself:
sudo ufw allow from <app-server-ip> to any port 27017
sudo ufw deny 27017
If both servers sit in the same datacenter, use a private network IP for bindIp and the firewall rule, not the public one. Never bind to 0.0.0.0 and rely on the app-level password alone — credential-stuffing bots don't care that you set a password if the port is open to the whole internet.
Common connection errors and what actually causes them
"MongoServerError: Authentication failed"
Almost always one of three things: wrong authenticationDatabase (it defaults to the database you're connecting to, not admin, unless you specify it), a password with special characters that need URL-encoding in the connection string, or a user created in the wrong database. Double-check with:
mongosh "mongodb://myapp_user:PASSWORD@localhost:27017/myapp_db?authSource=myapp_db"
"connect ECONNREFUSED" from a remote app server
This is a bindIp or firewall problem, not an auth problem. Check what Mongo is actually listening on:
sudo ss -tlnp | grep 27017
If it only shows 127.0.0.1:27017, your bindIp change either wasn't saved or the service wasn't restarted. If it shows the right IP but the connection still refuses, it's the firewall — check both UFW on the VPS and any security group/cloud firewall in front of it.
"connect ETIMEDOUT" instead of ECONNREFUSED
A refused connection means a firewall actively rejected the packet; a timeout usually means it was silently dropped — typically a cloud provider's network-level firewall (a security group, not UFW) sitting in front of the VPS. Check your provider's firewall/security group rules for port 27017, not just the OS-level one.
mongod won't start after a config change
YAML is whitespace-sensitive, and a stray tab instead of spaces will silently break the config. Validate the syntax and read the actual error before guessing:
sudo mongod --config /etc/mongod.conf --configExpand rest
sudo journalctl -u mongod -n 50 --no-pager
The log almost always names the exact line that's wrong.
Disk fills up fast, faster than expected
MongoDB's WiredTiger engine pre-allocates journal files and keeps oplog history, so disk usage grows faster than raw document size suggests. Check what's actually using the space:
sudo du -sh /var/lib/mongodb/*
If journal/ is the bulk of it, that's normal and self-managing — don't delete journal files manually. If the data files themselves are the problem, look at whether TTL indexes or capped collections would fit your use case before just adding more disk.
Backing it up properly
Don't skip this — treat it the same as MySQL backups. mongodump gives you a consistent snapshot you can restore from without touching the raw data files:
mongodump --uri="mongodb://admin:PASSWORD@localhost:27017" --authenticationDatabase=admin --out=/backups/mongo/$(date +%F)
mongorestore --uri="mongodb://admin:PASSWORD@localhost:27017" --authenticationDatabase=admin /backups/mongo/2026-07-22
Put the dump command in a cron job and ship the output off-server (rclone to object storage, or at minimum a different disk) — a backup that lives next to the database it backs up doesn't survive the VPS dying.
Prevention checklist
- Enable
authorization: enabledbefore you create a single real collection, not after. - Never bind to
0.0.0.0— setbindIpexplicitly and firewall the port to known IPs only. - Give each application its own scoped user; don't share the admin account.
- Run
mongodumpon a schedule and copy it off the server. - Keep MongoDB on the official repo so you actually get security patches — the distro-bundled fork often doesn't.
Frequently asked questions
Is MongoDB safe to run on a shared cPanel hosting plan?
No — MongoDB needs its own service and open ports, which shared hosting doesn't provide. Run it on a VPS where you control the firewall and can bind it to trusted IPs only.
Do I need authentication if MongoDB only listens on localhost?
Yes. Enable it anyway. Apps on the same server, other users on the box, or a future config change that accidentally opens the port are all still risks — auth is cheap insurance.
Why did my MongoDB get wiped with a ransom note in a collection?
This happens to instances left open with no authentication and bound to all interfaces. Automated bots scan for exactly this and drop your data, replacing it with a demand for payment. There's usually no data to recover — restore from backup and lock down bindIp and auth immediately.
What's the difference between MongoDB's bindIp and a firewall rule?
bindIp controls which network interfaces mongod listens on at all; the firewall controls who can reach that port. Use both — bindIp to avoid listening on the public interface unnecessarily, and the firewall to restrict access even on interfaces it does listen on.
Can I run MongoDB and MySQL on the same VPS?
Yes, they don't conflict — different ports, different data directories. Just make sure the VPS has enough RAM for both, since each keeps its own working set in memory, and watch total disk usage between the two.