Databases

Secure MongoDB Remote Access with bindIp and Authentication

Configure bindIp, enable authorization and restrict port 27017 so MongoDB accepts remote connections from your app server only.

IntermediateLinux server6 min read

MongoDB remote access requires three changes: bind the daemon to an address your app server can reach, turn on authorization so every connection needs a user, and restrict port 27017 to known client IPs. Do all three in that order and your database stays private while remaining reachable from your application.

By default MongoDB listens only on 127.0.0.1 and has no authentication. Opening the port without the other two steps is how databases end up indexed by search engines and wiped. This guide walks through the safe sequence on Ubuntu, Debian, AlmaLinux or Rocky.

Before you start

You need:

  • A Linux VPS with MongoDB already installed and running (sudo systemctl status mongod).
  • mongosh available on the server. On Ubuntu and Debian it ships with mongodb-mongosh; on RHEL-family systems install it from the MongoDB repository.
  • Root or sudo access, and the ability to edit /etc/mongod.conf.
  • The public IP of the machine that will connect, for example 198.51.100.25. This guide uses 203.0.113.10 as the server address.

Warning: Back up the config before editing it: sudo cp /etc/mongod.conf /etc/mongod.conf.bak. A YAML indentation mistake stops mongod from starting.

If MongoDB is not installed yet, follow How to install MongoDB on Ubuntu and secure it first, then come back here.

Confirm the current state

Check what the daemon is listening on:

Bash
sudo ss -tlnp | grep 27017

You should see 127.0.0.1:27017. That confirms remote connections are refused right now, which is the correct starting point.

Connect locally and list the databases:

Bash
mongosh --host 127.0.0.1 --port 27017
JavaScript
show dbs

If show dbs returns data without asking for a password, authorization is still off. Leave this shell open for the next step.

Create the admin user before enabling authorization

Create users first. If you enable authorization with no users defined, you lock yourself out of everything except the localhost exception.

In the mongosh session, switch to the admin database and create an administrative account:

JavaScript
use admin
db.createUser({
  user: "siteAdmin",
  pwd: passwordPrompt(),
  roles: [
    { role: "userAdminAnyDatabase", db: "admin" },
    { role: "readWriteAnyDatabase", db: "admin" }
  ]
})

passwordPrompt asks you to type the password instead of leaving it in your shell history. Note the output — it should report ok: 1.

Now create a least-privilege account for the application. Replace appdb with your real database name:

JavaScript
use appdb
db.createUser({
  user: "deploy",
  pwd: passwordPrompt(),
  roles: [ { role: "readWrite", db: "appdb" } ]
})

Tip: Give each application its own user scoped to its own database. A single shared root account makes auditing impossible and turns one leaked password into a full compromise.

Allow MongoDB remote access with bindIp

Open the config file:

Bash
sudo nano /etc/mongod.conf

Find the net section and set bindIp to the loopback address plus the address the app server should reach. If your VPS has a private network interface, bind to that instead of the public IP — traffic then never crosses the public internet.

YAML
net:
  port: 27017
  bindIp: 127.0.0.1,203.0.113.10

YAML is whitespace-sensitive. Use two spaces for the nested keys, not tabs, and keep the indentation of port and bindIp identical.

In the same file, enable authorization:

YAML
security:
  authorization: enabled

If the security block does not exist, add it at the end of the file.

Warning: Restarting mongod drops every open connection. Schedule this for a maintenance window if the database is already serving traffic.

Bash
sudo systemctl restart mongod
sudo systemctl status mongod

Confirm the daemon picked up the new bind address:

Bash
sudo ss -tlnp | grep 27017

You should now see 203.0.113.10:27017 alongside 127.0.0.1:27017.

Restrict port 27017 with the firewall

Binding to a public IP exposes the port to the internet. Close it to everything except your app server.

On Ubuntu or Debian with UFW:

Bash
sudo ufw allow from 198.51.100.25 to any port 27017 proto tcp
sudo ufw deny 27017/tcp
sudo ufw status numbered

On AlmaLinux or Rocky with firewalld, use a rich rule:

Bash
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="198.51.100.25" port port="27017" protocol="tcp" accept'
sudo firewall-cmd --reload
sudo firewall-cmd --list-rich-rules

If your provider also offers a cloud firewall or security group, add the same rule there. Host firewalls and network firewalls are independent layers.

Check it works

From the app server, connect with the application user:

Bash
mongosh "mongodb://deploy@203.0.113.10:27017/appdb?authSource=appdb"

Enter the password when prompted, then run:

JavaScript
db.runCommand({ ping: 1 })

A reply of { ok: 1 } means remote access and authentication both work. Try a write to be sure the role is correct:

JavaScript
db.test.insertOne({ check: "remote" })

Now verify the negative cases. From a machine that is not on the allow list, the connection should time out rather than be refused — that is the firewall dropping the packets. From the server itself, this should fail:

Bash
mongosh "mongodb://203.0.113.10:27017/appdb"

An authentication error here is the expected result. No credentials, no access.

Troubleshooting

  • MongoNetworkError: connection refused — mongod is still bound to 127.0.0.1 only. Re-check the bindIp line in /etc/mongod.conf, confirm the indentation, and restart the service. sudo ss -tlnp | grep 27017 shows the truth.
  • MongoNetworkError: connection timed out — the firewall is dropping packets. Confirm the client IP in your UFW rule or firewalld rich rule matches the source address exactly, and check any cloud security group.
  • MongoServerError: Authentication failed — the password is wrong, or authSource points at the wrong database. Users created inside appdb must authenticate against appdb, not admin.
  • MongoServerError: not authorized on appdb to execute command — the user exists but lacks the role. Grant readWrite on that database with db.grantRolesToUser while connected as an admin user.
  • mongod will not start after the edit — almost always a YAML problem. Run sudo journalctl -u mongod -n 50 to see the parse error, then restore /etc/mongod.conf.bak and redo the edit with consistent two-space indentation.

Next steps

Was this guide helpful?

Still stuck?

Ask MdmHost AI for a quick answer, or open a ticket and our team will take a look. We are here 24/7.