...

How to Install MongoDB on Ubuntu: Users, Secure Access, and Backups

Martin Klein

Reading time 1 minute

If you only need a working procedure without detailed explanations, here is a concise sequence for setting up MongoDB on Ubuntu, from installation and user creation to secure access and backup and restore testing.

  1. Install MongoDB Community Edition from the official repository and make sure the mongod service is running.
  2. While MongoDB is accepting connections only on 127.0.0.1, create an administrative user. Then enable mandatory authentication in /etc/mongod.conf:
 security:
  authorization: enabled

Then restart MongoDB.

  1. Create a separate application user with the minimum required privileges, such as readWrite access to app_db only.

The connection string will look something like this:

 mongodb://app_user:[email protected]:27017/app_db?authSource=app_db
  1. If the application is hosted on another server, configure MongoDB to listen on the required interface using bindIp, and allow 27017/tcp through the firewall only for the trusted IP address. Do not expose MongoDB to the internet without network access restrictions.
  2. Create test data and verify that app_user can read and modify its assigned database but does not have administrative privileges.
  3. Create a backup:
 mongodump --db app_db --out /var/backups/mongodb

Then delete the test database and restore it:

 mongorestore --db app_db /var/backups/mongodb/app_db
  1. After the restore, reconnect to MongoDB and verify that the collections and documents have been restored.

If this entire process completes successfully—the service starts, authentication works, the application connects using a dedicated user, and the backup can be restored—the basic MongoDB installation can be considered ready for continued use.

What This Article Covers

In this article, we will set up MongoDB on Ubuntu from scratch and configure it for use in a small project. We will create an administrative user and a separate application account, enable mandatory authentication, restrict network access, and examine common connection errors.

We will then test the backup process rather than simply creating a backup file. We will add actual documents, create a backup with mongodump, delete the test database, restore it with mongorestore, and verify that the data has been successfully restored.

Before moving on to the server architecture, let us briefly review the key terms.

MongoDB is a document-oriented database. Instead of conventional tables and rows, it stores data as documents organized into collections. Multiple collections associated with the same application or service are stored within a database.

The MongoDB server runs as the mongod process. It accepts client connections, executes queries, manages data on disk, and enforces security settings.

MongoDB Server Architecture

As usual, before installing packages and editing mongod.conf, let’s review the setup we want to create.

We will use a single Ubuntu VPS running MongoDB Community Edition. The mongod server process will run on it, and the application will connect to its own database using a dedicated user account with limited privileges.

We will use the administrative account only to manage MongoDB itself: creating users, changing privileges, and performing other administrative tasks.

This gives us a clear separation between two roles:

  • admin manages MongoDB;
  • app_user works only with the application’s data.

Initially, MongoDB will be accessible only locally via 127.0.0.1. This will allow us to create users and enable authorization safely before the database becomes accessible from other servers.

Once we have verified the local setup, we will configure remote access separately—but only if it is actually needed.

What We Will Install and Verify

The main MongoDB server process is called mongod.

It handles data storage, query processing, user management, and network connections.

To work with MongoDB from the terminal, you will need the MongoDB Shell: mongosh.

We will use it to:

  • Create users;
  • Switch between databases;
  • Add documents;
  • Verify permissions;
  • Delete the test database;
  • Verify the restore results.

For backup and restore, we will need separate utilities:

 mongodump
mongorestore

Finally, we will test the complete workflow:

Now that we understand the overall setup, let’s look at how the application itself will interact with MongoDB.

How the Application Will Connect to MongoDB

Applications typically connect to MongoDB using a connection URI.

For our local setup, it will look something like this:

 mongodb://app_user:[email protected]:27017/app_db?authSource=app_db

This URI specifies:

  • app_user — the application user;
  • password — the user’s password;
  • 127.0.0.1 — the MongoDB address;
  • 27017 — the default port;
  • app_db — the application database;
  • authSource=app_db — the database in which MongoDB should look for the user.

The last parameter is important. A MongoDB user is created in a specific authentication database, and an incorrect authSource can cause an authentication error even when the username and password are correct.

We will therefore create a dedicated application user with a clearly defined set of permissions:

This user will be able to read and modify application data but will not have administrative access to the entire server.

Before creating this account, MongoDB itself must be configured securely.

Why Configure Local Access First

There is no reason to expose MongoDB to external networks immediately after installation.

Until we have created an admin user and enabled mandatory authentication, it is safer to keep mongod accessible only via 127.0.0.1.

This means that the database can be accessed only from the VPS itself.

The sequence is straightforward:

  1. Install MongoDB;
  2. Check the service;
  3. Create an admin user;
  4. Enable authorization;
  5. Create app_user;
  6. Verify its permissions;
  7. Only then decide whether external access is required.

If the application runs on the same VPS, MongoDB can remain accessible only through localhost.

If the application runs on another server, we can later allow connections only from its trusted IP address and separately restrict access using the firewall.

This approach avoids initially creating a potentially exposed database and expands access only after users and authorization have been configured.

What to Prepare Before Installation

Before you begin, you will need only a small set of prerequisites:

ComponentPurposeWhat to Prepare
Ubuntu VPSMongoDB serverSSH access, CPU, RAM, and SSD
MongoDB Community EditionData storageA supported Ubuntu version
mongosh AdministrationLocal access to the server
MongoDB Database ToolsBackup and restoremongodump and mongorestore 
Admin userMongoDB managementA separate, secure password
app_user Application accessA password and permissions restricted to app_db 
app_db Working databaseAlso used for test data
Backup storageStoring backupsA local directory and, preferably, external storage
Trusted IPRemote accessRequired only when connecting from another server

The sequence for the remaining configuration steps is now clear: first, install MongoDB and secure local access; then separate the administrative and application users; and only after that proceed with network configuration and backups.

Choosing a MongoDB Version and VPS Configuration

We have already covered the overall architecture: MongoDB will run on a single Ubuntu VPS, the application will connect using a dedicated user account, and administrative privileges will remain exclusive to admin. The next step is to select a specific MongoDB version and determine how many resources are sufficient for a small production server.

The key is to strike the right balance. For testing, MongoDB can run on a very modest VPS, but for continuous operation, it is best to allow some headroom for memory and disk capacity from the outset. These two resources have a significant impact on database responsiveness, especially once indexes, regular writes, and backups are introduced.

In this guide, we use MongoDB 8.0 Community Edition on Ubuntu 24.04 LTS.

Resource Requirements for a Small MongoDB Deployment

MongoDB does not require a large server for a small project.

For a test environment, a small internal service, or an application handling a moderate number of requests, a few vCPUs and several gigabytes of RAM are sufficient to get started.

A practical baseline for a small standalone MongoDB deployment is:

  • 2 vCPUs
  • 4 GB of RAM
  • 40–60 GB of SSD storage

This is sufficient to:

  • Run mongod;
  • Store a small working database;
  • Create indexes;
  • Run mongodump;
  • Restore data using mongorestore;
  • Leave enough memory available for the filesystem cache.

A server with 1 vCPU and 2 GB of RAM can also work, especially for lab environments, but it provides little headroom. As the data, indexes, or workload grow, memory is exhausted much more quickly.

Therefore, for this article, we will not use the absolute minimum configuration. It is more important to have a predictable environment in which we can comfortably complete the entire process from installation to restore.

Why RAM and Disk Matter for MongoDB

MongoDB makes extensive use of memory for caching.

The WiredTiger storage engine keeps some frequently accessed data in its own cache, while Linux also uses available RAM for the filesystem cache. As a result, frequently read data does not need to be retrieved from disk every time.

For this reason, what matters for the database is not only how much memory is shown as used, but also how much remains available to the system.

If RAM runs low and the server starts using swap continuously, latency increases. Swap should be treated as an emergency reserve rather than a regular extension of RAM.

The situation is similar with disk storage.

MongoDB constantly works with:

  • Data files;
  • Indexes;
  • Journal;
  • Temporary files;
  • Logs.

A slow disk directly affects data read and write performance.

For this reason, an SSD is preferable for a production server. This becomes especially noticeable once the database no longer fits entirely in memory and MongoDB has to access storage more frequently.

In addition to speed, sufficient free space is important. A database may occupy only a few gigabytes today, but indexes, backups, and temporary data will add to its storage requirements later.

Therefore, disk capacity should not be provisioned without sufficient headroom.

Configuration Used in This Article

For our environment, we will use:

  • Ubuntu 24.04 LTS;
  • MongoDB 8.0 Community Edition;
  • 2 vCPU;
  • 4 GB RAM;
  • 60 GB SSD;
  • A single standalone mongod process;
  • The standard WiredTiger storage engine.

This is sufficient for a small database.

This will allow us to:

  • Create users;
  • Add data;
  • Check indexes and access permissions;
  • Create a backup;
  • Delete the test database;
  • Restore it;
  • Maintain adequate resource headroom on the server.

If MongoDB is later used for a larger project, resources should be increased based on the actual workload: monitor RAM usage, disk I/O, working set size, and query frequency. Alternatively, MongoDB supports horizontal scaling with separate instances on different VPSs.

For comparison, consider three scenarios:

ResourceMinimum Test EnvironmentSmall Production ServerArticle Configuration
CPU1 vCPU2+ vCPU2 vCPU
RAM2 GB4+ GB4 GB
Disk20–30 GB40–60+ GB SSD60 GB SSD
SwapSmall reserveAs a safety net onlyTo be checked separately
PurposeLab / testingSmall applicationHands-on training environment

All that remains is to verify that the actual VPS matches the selected specifications.

Server Check Commands

First, check the Ubuntu version:

 lsb_release -a

If lsb_release is not available, use:

 cat /etc/os-release

In our case, Ubuntu 24.04 LTS should be installed.

Number of available CPUs:

 nproc

For more detailed information:

 lscpu

Now check the memory:

 free -h

The values of interest are the total RAM and the available value.

Check swap separately:

 swapon --show

If the command produces no output, there is no active swap.

Now check the disks:

 lsblk

Then check the available disk space:

 df -h

MongoDB will later store its data in:

 /var/lib/mongodb

It is therefore especially important to check the partition containing this directory.

The main commands can be summarized in a quick-reference table:

What to CheckPurposeCommand
UbuntuCheck the operating system versionlsb_release -a 
CPUEnsure that sufficient CPU resources are availablenproc 
RAMCheck the total and available memoryfree -h 
SwapCheck the available virtual memory reserveswapon --show 
DisksView devices and partitionslsblk 
Free SpaceCheck available capacity for data and backupsdf -h 

Installing MongoDB on Ubuntu

Now that we have selected the version and allocated the resources, we can proceed with installing MongoDB on Ubuntu.

At this stage, the task is straightforward: add the official repository, install the required packages, start mongod, and verify that MongoDB Shell can connect to the local server. We will not enable authentication yet—the first step is to get a working basic installation.

Why Use the Official MongoDB Repository

MongoDB is available in Ubuntu’s system repositories, but for an up-to-date Community Edition, it is better to use the official MongoDB repository.

This provides several benefits:

  • You can install the desired MongoDB version;
  • Packages are updated from the same source;
  • The installation layout matches the standard MongoDB documentation;
  • You can install mongosh and Database Tools along with the server;
  • Upgrades between versions are easier to manage.

This article uses MongoDB 8.0, so we will configure the repository for this release branch.

After that, MongoDB can be installed with apt, just like other Ubuntu packages.

Packages Included with MongoDB

The main metapackage is:

 mongodb-org

It installs the components required for a standard standalone server.

The key components are:

  • mongodb-org-server — the mongod server process;
  • mongodb-mongosh — the MongoDB Shell;
  • mongodb-org-tools — a set of additional utilities;
  • MongoDB Database Tools — including mongodump and mongorestore.

The most important component is mongod.

It accepts connections, works with databases and collections, stores documents, and manages the storage engine.

mongosh is used by administrators and developers to run queries and manage MongoDB.

We will need mongodump and mongorestore later, when we cover the complete backup cycle.

How the mongod Service Works

After MongoDB is installed, the server runs as a systemd service:

 mongod.service

You can check its status with:

 sudo systemctl status mongod

For a quick check:

 sudo systemctl is-active mongod

If the service is running, the command will return:

 active

To configure MongoDB to start automatically after a reboot:

 sudo systemctl enable mongod

Use the standard commands to manage the service:

 sudo systemctl start mongod
sudo systemctl stop mongod
sudo systemctl restart mongod

If MongoDB fails to start, check the systemd logs first:

 sudo journalctl -u mongod -n 100 --no-pager

This command will be especially useful later, when we begin modifying mongod.conf: a YAML error or an invalid parameter can prevent the service from starting.

Where Configuration, Data, and Logs Are Stored

After a standard installation, the main files are stored in predictable locations.

Configuration:

 /etc/mongod.conf

This is where we will later enable authorization and change network settings such as bindIp.

By default, MongoDB data is stored in:

 /var/lib/mongodb

This directory contains WiredTiger files and other database data.

Logs:

 /var/log/mongodb/mongod.log

This gives us three key paths:

 /etc/mongod.conf
/var/lib/mongodb
/var/log/mongodb/mongod.log

The first path is for configuration, the second for data, and the third for diagnostics.

When troubleshooting, it is therefore important to know where to look: mongod.conf for configuration, systemctl and the journal for service startup issues, and mongod.log for MongoDB errors.

We can now proceed with the installation.

Hands-on: Installing and Running MongoDB

First, update the package index:

 sudo apt update

Install the utilities required to add the repository:

 sudo apt install -y curl gnupg

Add the MongoDB GPG key:

 curl -fsSL https://pgp.mongodb.com/server-8.0.asc | \
  sudo gpg -o /usr/share/keyrings/mongodb-server-8.0.gpg \
  --dearmor

Now add the repository for Ubuntu 24.04:

 echo "deb [ arch=amd64,arm64 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

Update the package index:

 sudo apt update

Install MongoDB:

 sudo apt install -y mongodb-org

Check the installed server version:

 mongod --version
Check the shell version:
mongosh --version
Check that Database Tools are available:
mongodump --version
mongorestore --version

Now start MongoDB:

 sudo systemctl start mongod

Enable the service to start automatically:

 sudo systemctl enable mongod

Check the service status:

 sudo systemctl status mongod

For a quick check:

 sudo systemctl is-active mongod

Now try connecting:

 mongosh

If everything is working, MongoDB Shell will open.

Run a simple check:

 db.runCommand({ ping: 1 })

A successful response will contain:

 ok: 1

This confirms that mongod is running and accepting local connections.

To exit the shell, run:

 exit

The main installation and verification commands can be summarized in a short table:

TaskCommand
Install MongoDBsudo apt install -y mongodb-org 
Start the servicesudo systemctl start mongod 
Enable automatic startupsudo systemctl enable mongod 
Check the statussudo systemctl status mongod 
Connect using the shellmongosh 
Check the serverdb.runCommand({ ping: 1 }) 
View the logsudo tail -n 100 /var/log/mongodb/mongod.log 

The basic installation is now complete: mongod is running, the shell can connect, and the main paths and commands are clear.

The next step is to configure authentication. First, we will examine how users, the authentication database, and roles work in MongoDB, and then create the first administrative user.

Understanding MongoDB Authentication

Why MongoDB Should Not Be Left Without Authentication

As long as authentication is disabled, the mere fact that MongoDB is accessible over the network poses a risk.

If mongod listens only on:

 127.0.0.1

the risk is lower because connections can only be made from the server itself.

However, if you later change bindIp and expose MongoDB to the network without configuring users, any client that can reach port 27017 could potentially interact with the data without proper authentication.

That is why we configure MongoDB in the following order:

  1. First, set up MongoDB for local access;
  2. Then create an administrative user;
  3. Next, make authentication mandatory;
  4. Then create the application user;
  5. Only after that should you enable remote access, if it is needed at all.

This approach is safer and easier to understand: establish the access mechanism first, then expand network access.

What Are a User and an Authentication Database?

In MongoDB, a user is not created globally on the server, but within a specific database.

For example:

 use app_db

and then:

 db.createUser({
    user: "app_user",
    pwd: "StrongPassword",
    roles: [
      { role: "readWrite", db: "app_db" }
    ]
})

In this case, the authentication database for app_user is:

 app_db

This is where MongoDB stores the user account and verifies the credentials.

Therefore, the connection string must account for both the application database and authSource.

For example:

 mongodb://app_user:[email protected]:27017/app_db?authSource=app_db

Here, both databases are the same:

  • The application uses app_db;
  • The user is also created in app_db.

However, they do not have to be the same.

For example, an administrative user is often created in:

 admin

The connection may then look like this:

 mongodb://admin_user:[email protected]:27017/?authSource=admin

If authSource is specified incorrectly, MongoDB will look for the user in a database other than the one in which the user was created, causing authentication to fail.

Later, we will intentionally reproduce this scenario when troubleshooting an Authentication failed error.

How an Administrative User Differs from an Application User

An administrative user is needed to manage the server itself.

This user can:

  • Create other users;
  • Assign roles;
  • View databases;
  • Perform administrative operations;
  • Manage access.

An application does not need most of these capabilities.

A typical web application usually only needs to work with its own database:

 app_db

and perform read and write operations in it.

If an application connects using an administrative account, any error or vulnerability in the application can have far more serious consequences.

In simplified terms:

Therefore, separating users is not merely a formality.

We create a separate account for the application with only the minimum required permissions and use the admin account solely to administer MongoDB.

To assign these permissions appropriately, we need to understand how roles work.

How Roles Work

A role defines which actions a user is allowed to perform.

One of the most common application roles is:

 readWrite

It allows the user to read and modify data in the specified database.

For example:

 roles: [
  { role: "readWrite", db: "app_db" }
]

This user will be able to:

  • Run find operations;
  • Insert documents;
  • Modify them;
  • Delete data;
  • Create the necessary collections and indexes within the scope of the user’s permissions.

However, this does not make the user an administrator of the entire MongoDB server.

There is also a more restrictive role: read

It is suitable for services that only need to read data.

Administrative roles provide significantly broader capabilities. For example, the root role can be used for an administrative account if full control over the server is truly required.

In other words, the logic is simple: the role should match the user’s actual task.

Do not grant the root role if the application only needs readWrite access to a single database.

User Account Structure Used in This Article

To avoid confusion about users and permissions later, we will define two user accounts upfront.

The first:

 mongo_admin

We will create it in the following database:

 admin

and use it for administrative operations.

The second:

 app_user

We will create it in:

 app_db

and grant it only:

 readWrite

on this database.

This gives us the following structure:

UserAuthentication DBRolePurpose
mongo_admin admin root MongoDB and user management
app_user app_db readWrite for app_db Application access to its own data

This separation will prove useful almost immediately.

Creating an Administrative User

Now that you understand roles and the authentication database, you can create the first MongoDB user: an administrator.

It is best to complete this step before enabling mandatory authorization. While mongod is accessible only locally and does not accept external connections, you can safely create the admin user, verify the credentials, and only then disable anonymous access.

Why the First User Is Created Before Enabling Authorization

After enabling:

 security:
  authorization: enabled

MongoDB requires a user account for operations that were previously performed without authentication.

Therefore, it makes sense to first create a user account that we can use to continue administering MongoDB.

In our case, this is:

 mongo_admin

It will be created in the authentication database:

 admin

After that, we can enable authorization and log in to MongoDB with a username and password.

This keeps the sequence predictable:

  1. Connect locally without credentials;
  2. Create mongo_admin;
  3. Verify that the user exists;
  4. Enable authorization;
  5. Connect as admin.

If you reverse the order and restrict access too soon, the setup becomes considerably more cumbersome.

Required Administrator Privileges

For this guide, the administrative user needs full control over the MongoDB server.

We will therefore assign the following role:

 root

This role will allow mongo_admin to manage databases and users and perform other administrative operations.

In production, you can implement a more granular access model and separate responsibilities across multiple accounts. However, for a single small standalone server, a dedicated administrator account with the root role is a clear and practical approach.

Most importantly, do not use this account within the application itself.

The application will later have its own user account:

 app_user

with the readWrite role limited to app_db.

Now, let’s create the administrator account.

Practice: Create an Admin User and Verify Login

Connect locally:

 mongosh

Switch to the admin database:

 use admin

Create the user:

 db.createUser({
    user: "mongo_admin",
    pwd: passwordPrompt(),
    roles: [
      { role: "root", db: "admin" }
    ]
})

Using passwordPrompt() is preferable to entering the password directly in the command: the value is not shown in plaintext in the example or stored in the shell history as part of the command.

MongoDB will prompt for the password interactively.

After the user has been created successfully, verify the user:

 db.getUser("mongo_admin")

The output should show the username and the assigned root role.

Now exit the shell:

 exit

At this stage, authorization is not yet enabled, so simply creating the user does not yet cause MongoDB to require authentication for every connection.

However, you can already verify the credentials explicitly.

Connect as follows:

 mongosh --username mongo_admin --authenticationDatabase admin --password

After you enter the password, MongoDB Shell will open.

In the shell, you can verify the current user and run an administrative command:

 use admin
db.runCommand({ connectionStatus: 1 })

The response should include information about the authenticated user mongo_admin.

You can also run:

 show dbs

If the command succeeds, the administrative privileges have been applied correctly.

We now have a working administrative account and can proceed to the next important step: enabling mandatory authorization.

After that, running mongosh without credentials should no longer provide full access to data and administrative operations.

Enabling Mandatory Authentication

What Changes After Setting authorization: enabled

The key setting is:

 security:
  authorization: enabled

Once enabled, MongoDB begins enforcing role-based access control.

Simply connecting to the server is no longer sufficient. The client must authenticate as a specific user, after which MongoDB checks whether that user is authorized to perform the requested operation.

For example, an administrative user will be able to:

  • Create users;
  • View databases;
  • Modify roles;
  • Run administrative commands.

The future app_user, however, will be able to work only with app_db within the permissions granted by the readWrite role.

This is when the user separation configured earlier actually takes effect.

Where to Configure Security in mongod.conf

The main MongoDB configuration file is located at:

 /etc/mongod.conf

Open it:

 sudo nano /etc/mongod.conf

We need the security section.

If it does not exist yet, add it:

 security:
  authorization: enabled

Be sure to use the correct indentation. mongod.conf uses YAML, so a structural error may prevent mongod from starting after a restart.

You can also verify that the network settings remain restricted to local connections for now:

 net:
  port: 27017
  bindIp: 127.0.0.1

At this stage, this is exactly what we need: authorization is enabled, but MongoDB is still not accessible externally.

The next question is what a user will see if they try to connect without credentials.

What Happens When You Connect Without Credentials

After authorization is enabled, the command:

 mongosh

can still connect to the local mongod instance.

However, this does not mean that the client has full access to the data.

For example, the shell may open, but protected operations will return authorization errors.

If you try to list the databases:

 show dbs

MongoDB should reject the command because the client is not authenticated.

The same will happen when you attempt to perform operations that require privileges.

It is therefore important to distinguish between two concepts:

  • Connection to the server;
  • Authorized access to data.

A network connection may be established, but MongoDB will not allow protected operations without an authenticated user.

To use MongoDB normally after this, connect using a command such as:

 mongosh --username mongo_admin --authenticationDatabase admin --password

Now, we will enable authorization and verify this behavior in practice.

Hands-on: Enable authorization and restart MongoDB

Open the configuration file:

 sudo nano /etc/mongod.conf

Add:

 security:
  authorization: enabled

Together with the existing network settings, the relevant section of the file may look like this:

Save the file.

Now restart MongoDB:

 sudo systemctl restart mongod

Immediately check the service status:

 sudo systemctl status mongod

If you see:

 active (running)

the configuration has been applied.

If the service fails to start, first check:

 sudo journalctl -u mongod -n 100 --no-pager

and:

 sudo tail -n 100 /var/log/mongodb/mongod.log

Now test connecting without credentials:

 mongosh

In the shell, run:

 show dbs

MongoDB should report that the operation requires authentication.

Exit the shell:

 exit

Now connect with the correct credentials:

 mongosh --username mongo_admin --authenticationDatabase admin --password

After entering the password, run:

 show dbs

and:

 db.runCommand({ connectionStatus: 1 })

The commands should now run with the privileges assigned to mongo_admin.

The results can be summarized as follows:

ChangeWhat happensHow to verify
authorization: enabled MongoDB begins checking users and rolesRestart mongod 
Connection without credentialsA connection can be established, but protected operations are blockedmongosh → show dbs 
Connection as an administratorAccess is determined by the user’s rolemongosh --username mongo_admin --authenticationDatabase admin --password 
Error in mongod.conf mongod may fail to startsystemctl status and journalctl 

Anonymous access to MongoDB is now disabled, and administrative operations can be performed only after authentication.

Creating a Dedicated Application User

Authentication is already required, and mongo_admin can manage the server. The next step is to separate administrative access from the application’s day-to-day operations.

This is important: the application should not connect to MongoDB as the root user simply because “it’s easier.” We will create a separate account with permissions limited to the application’s working database.

Why the application should not run as an administrator

An administrative user has privileges that are far too broad for a regular application.

If the application connects as mongo_admin, it could potentially:

  • Access other databases;
  • Create and delete users;
  • Modify roles;
  • Run administrative commands;
  • Affect the entire MongoDB server if there is an error in the code.

An application does not need these privileges.

It typically needs far fewer permissions:

  • Read its own data;
  • Add documents;
  • Modify them;
  • Delete them;
  • Create the required indexes.

Therefore, it is better to create a separate user:

 app_user

and restrict it to:

 app_db

If the application is later compromised, the blast radius will at least be limited to this database rather than the entire server.

How to Restrict a User to a Single Database

A MongoDB user is created in a specific authentication database and assigned roles that specify the databases to which they apply.

For our application, switch to:

 use app_db

and create the user there.

The user’s authentication database will then also be:

 app_db

This is also convenient for the connection string:

 mongodb://app_user:[email protected]:27017/app_db?authSource=app_db

With this approach, the user account and the application database are logically located in the same place.

Permissions are assigned through roles.

For example:

 roles: [
  { role: "readWrite", db: "app_db" }
]

This grants the user read and write access only to app_db.

The user does not become an administrator or automatically receive permissions for other databases.

Roles Required for Read and Write Access

For a typical application, the following role is usually appropriate:

 readWrite

It allows the user to work with data in a specific database.

A user with the readWrite role can:

  • Read documents;
  • Insert new documents;
  • Update existing documents;
  • Delete documents;
  • Create collections;
  • Work with indexes within the scope of the role’s permissions.

If a service only needs to read data, you can use a more restrictive role:

 read

For example, this may be sufficient for a dedicated reporting service.

However, our test application requires full standard CRUD access, so we will use:

 readWrite

for app_db.

Now we will create a user and immediately test several scenarios: a successful write, a successful read, a lack of administrative privileges, and an error caused by an incorrect password.

Hands-on: Creating app_user and Verifying Permissions

First, connect as the administrative user:

 mongosh --username mongo_admin --authenticationDatabase admin --password

Switch to the application database:

 use app_db

Create the user:

 db.createUser({
    user: "app_user",
    pwd: passwordPrompt(),
    roles: [
      { role: "readWrite", db: "app_db" }
    ]
})

After creating the user successfully, verify the account:

 db.getUser("app_user")

The output should show the following role:

 readWrite

for:

 app_db

Now exit:

 exit

Then connect as the application user:

 mongosh \
  --username app_user \
  --authenticationDatabase app_db \
  --password \
  app_db

After you enter the correct password, the shell should open.

Now test write access.

Create a collection and insert a document:

 db.users.insertOne({
    name: "Alice",
    email: "[email protected]",
    active: true
})

If the write succeeds, MongoDB returns a result containing acknowledged: true and insertedId.

Now test read access:

 db.users.find()

The inserted document should appear in the output.

Next, test update access:

 db.users.updateOne(
  { name: "Alice" },
  { $set: { active: false } }
)

Query the data again:

 db.users.find({ name: "Alice" })

The active field should now be false.

You can also test delete access:

 db.users.deleteOne({ name: "Alice" })

This confirms that the user can work with data in its own database.

Now verify the other side of the access model: the absence of administrative privileges.

For example, try switching to admin and requesting the list of users:

 use admin
db.getUsers()

app_user should not have administrative access to user management.

You can also try creating a user:

 db.createUser({
    user: "should_not_work",
    pwd: passwordPrompt(),
    roles: []
})

The operation should fail with an authorization error.

Now test an incorrect password.

Exit the shell:

 exit

Then try to connect as follows:

 mongosh \
  --username app_user \
  --authenticationDatabase app_db \
  --password \
  app_db

At the password prompt, deliberately enter an incorrect value.

You should receive an error similar to the following:

 Authentication failed

This is an important check: MongoDB does not merely recognize the user; it actually validates the credentials.

Afterward, reconnect using the correct password and confirm that access has been restored.

For the final verification, use these four test scenarios:

TestExpected result
Write to app_db Successful
Read from app_db Successful
Administrative commandAccess denied / Unauthorized
Incorrect passwordAuthentication failed 

The access model now works as intended: mongo_admin manages the server, while app_user works only with its own database.

The next step is the network layer. We will examine bindIp, port 27017, and how to allow remote access only from a trusted address without exposing MongoDB externally without restrictions.

Configuring Secure Network Access

Why MongoDB Should Not Be Exposed to the Entire Internet by Default

MongoDB is a database server, not a public web service.

If port 27017 is open to all addresses, any client on the internet can at least attempt to connect to mongod.

Even with authorization enabled, this creates an unnecessary attack surface:

  • Repeated attempts to guess credentials;
  • Port scanning;
  • Unnecessary load;
  • The risk of errors in user configuration;
  • The risk of accidentally disabling authentication in the future and leaving the database exposed.

Therefore, it is best to configure access according to the following principle: MongoDB listens only on the interfaces where it is actually needed, and the firewall allows traffic only from trusted sources.

Ideally, both restrictions should be applied together.

The first is configured using bindIp.

The second is configured through the firewall.

How bindIp Works

The bindIp parameter specifies which network interfaces mongod accepts connections on.

It is located in the net section of the following file:

 /etc/mongod.conf

For example:

 net:
  port: 27017
  bindIp: 127.0.0.1

With this configuration, MongoDB listens only on localhost.

This means you can connect from the VPS itself:

 mongosh

However, another server on the network will not be able to connect to port 27017.

To also allow connections through the server’s private IP address, specify both addresses:

 net:
  port: 27017
  bindIp: 127.0.0.1,10.0.0.10

mongod now listens on:

  • localhost;
  • the private interface at 10.0.0.10.

It is important to understand: bindIp determines exactly where MongoDB listens for connections.

It is not a replacement for a firewall.

Even if mongod listens on a private or public interface, network access should still be restricted separately using firewall rules.

When 127.0.0.1 Is Sufficient

If the application runs on the same VPS, there is no need to expose anything externally.

The setup is straightforward:

Connection string:

 mongodb://app_user:[email protected]:27017/app_db?authSource=app_db

This is one of the simplest and most secure options.

Port 27017 is not accessible externally, and the application communicates with the database through the loopback interface.

This setup should be retained unless there is a specific reason to allow remote connections.

The fewer network interfaces MongoDB listens on, the fewer settings there are to secure and troubleshoot.

When Remote Access Is Required

Remote access is required when the application and MongoDB are hosted on different servers.

For example: Application VPS → MongoDB VPS

In this case, the database must accept connections at an address accessible to the application.

It is best to use a private network if the cloud provider offers one.

For example:

Then you can keep the following configuration in mongod.conf:

 net:
  port: 27017
  bindIp: 127.0.0.1,10.0.0.10

The application will then connect to:

 mongodb://app_user:[email protected]:27017/app_db?authSource=app_db

This way, database traffic does not need to be exposed to the public internet at all.

If no private network is available and you have to use a public IP address, it is especially important to configure the firewall to allow access only from the application’s specific trusted IP address.

Undesirable configuration: 0.0.0.0:27017 → accessible to everyone

Acceptable configuration: MongoDB public IP:27017 → accessible only from the application’s IP address

Now let’s configure this second layer of protection.

How to restrict access to port 27017 using a firewall

Assume the application’s trusted IP address is:

 203.0.113.20

If you use UFW, you can allow connections only from this address:

 sudo ufw allow from 203.0.113.20 to any port 27017 proto tcp

Check the rules:

 sudo ufw status numbered

Do not add:

 sudo ufw allow 27017/tcp

if MongoDB should not be accessible to everyone.

This rule would open the port to connections from any source, which is exactly what we want to avoid.

If the VPS is hosted by a cloud provider with a separate network firewall or security group, apply the same restriction there as well.

This results in two layers: cloud firewall → UFW → mongod bindIp

For the connection to succeed, all three layers must allow the required route.

Practical example: Allowing Access from a Trusted Address Only

Assume the MongoDB VPS has the following private IP address:

 10.0.0.10

and the application has:

 10.0.0.20

Open the configuration file:

 sudo nano /etc/mongod.conf

Configure the net section:

 net:
  port: 27017
  bindIp: 127.0.0.1,10.0.0.10

Save the file and restart MongoDB:

 sudo systemctl restart mongod

Check the service status:

 sudo systemctl is-active mongod

Now check which addresses the port is actually listening on:

 sudo ss -lntp | grep 27017

The output should include only the required addresses.

If UFW is used, allow access from the application server:

 sudo ufw allow from 10.0.0.20 to any port 27017 proto tcp

Verify the rule:

 sudo ufw status

You can now test the TCP port from the application VPS:

 nc -vz 10.0.0.10 27017

If nc is not installed:

 sudo apt install -y netcat-openbsd

Then test a full connection:

 mongosh \
  "mongodb://[email protected]:27017/app_db?authSource=app_db" \
  --password

With the correct password, the user should be able to log in and access app_db.

The port should remain inaccessible from any other untrusted address.

For convenience, the main options are compared below:

SetupbindIp FirewallWhen to use
Localhost127.0.0.1 Port 27017 is closed to external accessThe application and MongoDB run on the same VPS
Private network127.0.0.1,10.0.0.10 Only the application’s private IP address is allowedBest option for two VPS instances on the same private network
Public networkLocalhost + the required public interfacePort 27017 is accessible only from a trusted public IP addressWhen a private network is unavailable

Let’s move on.

Testing the MongoDB Connection

Network access is already configured: a local client can connect to MongoDB via 127.0.0.1, while a remote server, if needed, is granted access only through a trusted address. The only remaining step is to verify that the connection string is correct and that MongoDB clearly distinguishes between a successful connection, an incorrect authSource, and an incorrect password.

It is useful to test several scenarios at this stage. This will make it easier to determine later whether an error is caused by the credentials, the authentication database, or the network itself.

Connection string format

To connect to MongoDB, you typically use a URI in the following format:

 mongodb://username:password@host:27017/database?authSource=authentication_database

In our case, the local connection string looks like this:

 mongodb://app_user:[email protected]:27017/app_db?authSource=app_db

Here:

  • app_user — the application user;
  • password — the user’s password;
  • 127.0.0.1 — the MongoDB address;
  • 27017 — the default port;
  • app_db — the application database;
  • authSource=app_db — the database in which the user was created.

For a remote connection, the main value to change is the host:

 mongodb://app_user:[email protected]:27017/app_db?authSource=app_db

or a trusted public IP address if the private network is unavailable.

In production, it is best not to pass the password directly on the command line because it may be saved in the shell history or exposed in the process list. For manual testing, use --password and enter the value interactively.

Why authSource Is Needed

MongoDB needs to know which database to search for the user account.

We created:

 app_user

in:

 app_db

Therefore, the correct authSource is:

 authSource=app_db

If you specify the following instead:

 authSource=admin

MongoDB will look for app_user in a different authentication database.

As a result, the password may be entirely correct, but authentication will still fail.

This is one reason why Authentication failed does not always mean “incorrect password.”

First, check all three of the following:

  • username;
  • password;
  • authSource.

Now let’s test the correct local setup.

How to test the local connection

Connect from the MongoDB VPS as follows:

 mongosh \
  "mongodb://[email protected]:27017/app_db?authSource=app_db" \
  --password

When prompted, enter the password for app_user.

If everything is configured correctly, MongoDB Shell will open.

Check the current database:

 db

Expected output:

 app_db

Now run a simple command:

 db.runCommand({ ping: 1 })

Then verify access to the data:

 db.users.find()

If the collection is still empty or does not exist, this is not a problem. The important thing is that the command runs without an Unauthorized error.

This confirms three things:

  • MongoDB is accessible locally;
  • the credentials work;
  • the user has permissions for app_db.

You can then test the same setup from another server.

How to Test a Remote Connection

On the Application VPS, first verify that the port is accessible:

 nc -vz 10.0.0.10 27017

If the connection succeeds, proceed to MongoDB authentication:

 mongosh \
  "mongodb://[email protected]:27017/app_db?authSource=app_db" \
  --password

After you enter the correct password, the shell should open just as it does with a local connection.

In the shell, you can run:

 db.runCommand({ ping: 1 })

and:

 db.users.find()

If the TCP port is completely inaccessible, the connection has not yet reached the authentication stage.

In that case, return to the previous layer and check:

  • bindIp;
  • UFW;
  • cloud firewall;
  • the MongoDB VPS IP address;
  • the network route between the servers.

In other words, connection and authentication errors occur at different stages.

What Should Happen When an Incorrect Password Is Used

Now, we will deliberately test a failure scenario.

Run the same command:

 mongosh \
  "mongodb://[email protected]:27017/app_db?authSource=app_db" \
  --password

This time, enter an incorrect password.

MongoDB should reject the authentication attempt and return an error such as:

 Authentication failed

This is the expected behavior.

You can also test an incorrect authSource separately:

 mongosh \
  "mongodb://[email protected]:27017/app_db?authSource=admin" \
  --password

Even with the correct password, the connection attempt as app_user should fail because the user was created in app_db, not in admin.

We now have several test scenarios:

ScenarioConnection String / TestExpected Result
Local connection with valid credentialsmongodb://[email protected]:27017/app_db?authSource=app_db Successful authentication
Remote connection from a trusted servermongodb://[email protected]:27017/app_db?authSource=app_db Successful authentication
Incorrect passwordSame URI, incorrect passwordAuthentication failed 
Incorrect authSource authSource=admin for app_user Authentication failed 
Untrusted IP addressTest port 27017 from another addressThe connection is blocked by the firewall

The connection has now been tested for both network connectivity and authentication. The next step is to move from the infrastructure itself to the data: we will create a test collection, add several documents, and prepare them for the complete backup → deletion → restore cycle.

Writing Test Data

Creating a Test Database and Collection

MongoDB does not require you to create a database in advance using a separate command.

The database and collection are created when data is first written. Therefore, you only need to connect to app_db:

 mongosh \
  "mongodb://[email protected]:27017/app_db?authSource=app_db" \
  --password

After entering the password, verify that the correct database is selected:

 db

Expected output:

 app_db

You can create the collection explicitly:

 db.createCollection("products")

If the command succeeds, the output will include:

 ok: 1

Check the list of collections:

 show collections

It should now include:

 products

Explicitly creating the collection is not required here—MongoDB could create it automatically on the first insert. However, for step-by-step verification, it is more convenient to create the structure first and then add documents separately.

Adding Multiple Documents

Let’s add several documents at once using insertMany():

 db.products.insertMany([
    {
      sku: "TEST-001",
      name: "Mechanical Keyboard",
      price: 89.90,
      stock: 12,
      active: true
    },
    {
      sku: "TEST-002",
      name: "Wireless Mouse",
      price: 39.50,
      stock: 27,
      active: true
    },
    {
      sku: "TEST-003",
      name: "USB-C Dock",
      price: 119.00,
      stock: 5,
      active: false
    }
])

If the insert is successful, MongoDB will return:

 acknowledged: true

along with the _id values of the created documents.

This gives us a small but useful dataset. The documents are easy to distinguish by SKU, name, price, and stock level.

We will intentionally leave them unchanged until the backup. We will need to compare this database state with the result after restoration.

Verifying the inserted data

Let’s view all the documents:

 db.products.find()

For more concise output, you can display only the required fields:

 db.products.find(
  {},
  {
    _id: 0,
    sku: 1,
    name: 1,
    price: 1,
    stock: 1,
    active: 1
  }
)

You should see three documents:

  • TEST-001
  • TEST-002
  • TEST-003

Let’s count the documents:

 db.products.countDocuments()

Expected result: 3

You can also verify a specific document:

 db.products.findOne({ sku: "TEST-003" })

MongoDB should return the document for USB-C Dock.

We now have several useful checkpoints:

  • database — app_db;
  • collection — products;
  • document count — 3;
  • unique sku values — TEST-001, TEST-002, TEST-003.

After the restore, we will verify the same values. If the collection once again contains all three documents with their original fields, the restore has successfully recovered the data.

Hands-on: Preparing Data for Backup

Before creating a backup, let’s perform a final check.

First, let’s make sure we are working with the correct database:

 db

Result:

 app_db

Let’s check the collection:

 show collections

The list should include:

 products

Let’s check the number of documents:

 db.products.countDocuments()

The result is:

 3

Now let’s display the verification dataset:

 db.products.find(
  {},
  {
    _id: 0,
    sku: 1,
    name: 1,
    stock: 1
  }
).sort({ sku: 1 })

Before creating the backup, the output should look roughly like this:

 {
  sku: 'TEST-001',
  name: 'Mechanical Keyboard',
  stock: 12
}
{
  sku: 'TEST-002',
  name: 'Wireless Mouse',
  stock: 27
}
{
  sku: 'TEST-003',
  name: 'USB-C Dock',
  stock: 5
}

The test dataset is now ready.

Next, we will begin the main backup verification cycle:

The next step is to create a backup using mongodump and verify that it actually contains our app_db database before deleting anything.

Creating a Backup with mongodump

What mongodump saves

mongodump connects to a running MongoDB instance and exports the contents of its databases in BSON format.

A standard backup of a single database will have roughly the following structure:

The products.bson file contains the documents themselves.

The products.metadata.json file stores collection metadata, such as information about indexes and additional options.

If the database contains multiple collections, corresponding BSON and metadata files will be created for each one.

In other words, mongodump does not create a text-based export such as CSV, but instead saves the database structure in a format designed specifically for restoring MongoDB.

How a logical backup differs from copying MongoDB files

You might assume that simply copying the following directory would be sufficient:

 /var/lib/mongodb

However, this is a completely different approach.

This directory contains internal WiredTiger files, the journal, and operational data used by the running storage engine. Simply copying these files while mongod is running does not constitute a valid logical backup and may result in an inconsistent state.

mongodump operates at a higher level:

It connects to the server as a regular client and exports the data it can access.

This is useful for:

  • Backing up individual databases;
  • Migrating data between MongoDB servers;
  • Restoring individual collections;
  • Small and medium-sized data volumes;
  • Testing the restore procedure.

However, a logical backup is not a substitute for a comprehensive backup strategy for every workload. The larger the database and the heavier the write activity, the more important it is to plan for consistency, the backup window, and how backups will be stored.

How to provide credentials more securely

The most obvious approach would look like this:

 mongodump \
  --username app_user \
  --password MySecretPassword \
  --authenticationDatabase app_db \
  --db app_db

However, specifying a password on the command line is a bad idea.

It may remain in the shell history, end up in a script, or be accidentally saved along with other commands.

It is therefore better to provide only the username and have the utility prompt for the password interactively:

 mongodump \
  --username app_user \
  --authenticationDatabase app_db \
  --password \
  --db app_db

When you run the command, you will be prompted for the password.

Another option is to use a URI without a password:

 mongodump \
  --uri="mongodb://[email protected]:27017/app_db?authSource=app_db" \
  --password

In both cases, the secret is not included directly in the command.

If the backup is automated using cron or a systemd timer, credentials should be stored separately with restricted permissions rather than embedding the password directly in the shell command.

Where to store the backup

By default, mongodump creates a directory named dump in the current directory.

This is sufficient for a one-time test, but on a server, it is more convenient to designate a clear path in advance:

 /var/backups/mongodb

Create it:

 sudo install -d \
  -m 700 \
  -o "$(id -un)" \
  -g "$(id -gn)" \
  /var/backups/mongodb

Permissions 700 mean that only the directory owner can read and modify its contents.

This is especially useful because the backup contains actual application data.

However, keeping your only backup on the same VPS is not sufficient. If the server loses its disk, the backup will be lost along with MongoDB.

Therefore, the production strategy should be as follows:

For example, a second storage location, Object Storage, or a separate backup server.

First, we will create a local backup and test the full recovery cycle

Hands-on: Backing Up app_db

Before we begin, let’s verify once again that the source data exists.

Connect:

 mongosh \
  "mongodb://[email protected]:27017/app_db?authSource=app_db" \
  --password

Count the documents:

 db.products.countDocuments()

Expected result: 3

You can also display the test records again:

 db.products.find(
  {},
  {
    _id: 0,
    sku: 1,
    name: 1,
    stock: 1
  }
).sort({ sku: 1 })

After verifying the data, exit:

 exit

Now create a separate directory for this backup:

 mkdir -p /var/backups/mongodb/app-db-backup

Run mongodump:

 mongodump \
  --host 127.0.0.1 \
  --port 27017 \
  --username app_user \
  --authenticationDatabase app_db \
  --password \
  --db app_db \
  --out /var/backups/mongodb/app-db-backup

Enter the password for app_user.

If the operation succeeds, the output will include messages about dumping the products collection.

Now inspect the directory structure:

 find /var/backups/mongodb/app-db-backup -maxdepth 2 -type f

You should see something like this:

 /var/backups/mongodb/app-db-backup/app_db/products.bson
/var/backups/mongodb/app-db-backup/app_db/products.metadata.json

Check the size:

 du -sh /var/backups/mongodb/app-db-backup

Also inspect the contents of the database directory:

 ls -lh /var/backups/mongodb/app-db-backup/app_db

Before deleting the source database, make sure of at least the following three things:

  • mongodump completed without errors;
  • The app_db directory was created;
  • It contains products.bson.

The commands for different scenarios are as follows:

ScenarioExample
Dump all accessible databases on the servermongodump --username mongo_admin --authenticationDatabase admin --password --out /var/backups/mongodb/full 
Dump a single databasemongodump --username app_user --authenticationDatabase app_db --password --db app_db --out /var/backups/mongodb/app-db-backup 
Single archive filemongodump --username app_user --authenticationDatabase app_db --password --db app_db --archive=/var/backups/mongodb/app_db.archive.gz --gzip 

Archive mode is useful when you want a single compressed file instead of a directory containing multiple BSON files:

 app_db.archive.gz

For this demonstration, we’ll use a standard directory dump because it makes it easier to verify that the backup actually contains the products collection.

The backup now exists separately from the source database.

Deleting the Test Database

The backup has already been created and stored separately from the production MongoDB instance. Now we need to test it properly: delete the source database and verify that the data is no longer present.

This step distinguishes a genuine restore test from a scenario in which mongorestore is run against existing collections, making it impossible to determine exactly which data was restored from the backup.

Why Verify the Backup Again Before Deletion

Before running dropDatabase(), perform one final check.

After the source database is deleted, the dump will be the only remaining source of data. If the backup is empty, was written to the wrong directory, or failed to complete, there will be nothing to restore.

Therefore, check the files again:

 find /var/backups/mongodb/app-db-backup -maxdepth 2 -type f

The expected output is:

 /var/backups/mongodb/app-db-backup/app_db/products.bson
/var/backups/mongodb/app-db-backup/app_db/products.metadata.json

Check the size:

 du -sh /var/backups/mongodb/app-db-backup

Then check the directory contents separately:

 ls -lh /var/backups/mongodb/app-db-backup/app_db

If products.bson exists and mongodump completed without errors, you can proceed with the deletion.

As an additional check, you can review the source data again:

 mongosh \
  "mongodb://[email protected]:27017/app_db?authSource=app_db" \
  --password

In the shell:

 db.products.countDocuments()

Expected result: 3

And:

 db.products.find(
  {},
  {
    _id: 0,
    sku: 1,
    name: 1
  }
).sort({ sku: 1 })

You can then delete the database.

Hands-on: Run dropDatabase() and verify that the data is gone

We are already connected to:

 app_db

Let’s verify this:

 db

Expected output:

 app_db

Now run:

 db.dropDatabase()

If the database is deleted successfully, MongoDB returns output similar to the following:

 { ok: 1, dropped: 'app_db' }

The database has now been deleted along with its collections and documents.

Check the list of databases:

 show dbs

app_db should no longer appear in the list.

Now try listing the collections:

 show collections

Then run the following query:

 db.products.find()

Because the original database has been deleted, the previous documents are no longer there.

You can also check the document count:

 db.products.countDocuments()

For a collection that does not exist or has not been re-created, the result will be 0.

There is one important nuance to understand about this command:

 use app_db

It does not restore the database by itself.

It only switches the current shell context. The database will reappear only after data is written to it or it is restored using mongorestore.

Therefore, after running dropDatabase(), we intentionally do not insert any data manually.

The current state is now as follows:

The original data has now been deleted, and the only copy of the test dataset is in the backup.

The next step is to restore app_db using mongorestore and verify that the products collection once again contains all three original documents.

Restoring MongoDB with mongorestore

How mongorestore Reads mongodump Data

mongorestore works in conjunction with mongodump.

Previously, mongodump created the following structure:

mongorestore now reads these files and recreates the corresponding databases and collections in MongoDB.

In simplified terms, the process works as follows:

This restores both the documents and the metadata associated with the collection.

Because app_db has been completely deleted, this is the cleanest possible scenario: the restore operation should effectively recreate it from the dump.

What Happens to Existing Collections

If the database or collection already exists, mongorestore may not behave as expected.

Without additional options, the restore process attempts to add data from the backup to the existing collections.

This can lead to several scenarios:

  • Documents are added to the existing collection;
  • Conflicts occur over _id values;
  • Some records are already present;
  • The result is no longer an exact copy of the backup state.

This is why, before running a restore, you need to know exactly where the data will be loaded.

This issue does not apply to our current test: app_db has been deleted, so products will be created from scratch.

However, when restoring into an existing database, it is often more convenient to clear the target collections first.

This is what the --drop option is used for.

When to Use –drop

The option:

 --drop

instructs mongorestore to drop the corresponding collection before restoring it from the backup.

For example:

 mongorestore \
  --username app_user \
  --authenticationDatabase app_db \
  --password \
  --drop \
  /var/backups/mongodb/app-db-backup/app_db

The process is then as follows:

This is useful when you need to replace the current data with the data from the dump.

However, --drop should be used with care. If the existing collection contains new data that is not in the backup, it will be deleted.

In our scenario, app_db no longer exists, so --drop is not technically required. However, this option is useful to know because it often becomes important when performing subsequent restores.

Now, let’s restore the deleted database.

Hands-on: Restoring the Deleted app_db Database

First, verify that the backup is in place:

 find /var/backups/mongodb/app-db-backup -maxdepth 2 -type f

Expected output:

 /var/backups/mongodb/app-db-backup/app_db/products.bson
/var/backups/mongodb/app-db-backup/app_db/products.metadata.json

Now run the restore. There is an important detail here: although we completely deleted app_db using db.dropDatabase(), the app_user account created in that database was not deleted along with the data. MongoDB stores user information separately from application data collections, so dropDatabase() deletes the database data but not the associated user account.

Therefore, we can still authenticate as app_user during the restore by specifying app_db as the authentication database:

 mongorestore \
  --host 127.0.0.1 \
  --port 27017 \
  --username app_user \
  --authenticationDatabase app_db \
  --password \
  /var/backups/mongodb/app-db-backup/app_db

When prompted, enter the app_user password.

If the restore is successful, the output should include messages indicating that app_db.products was restored and showing the number of documents successfully imported.

Because all user data in app_db was deleted, mongorestore will recreate the required database collections, including products.

To restore the same data over an existing collection, use the following command:

 mongorestore \
  --host 127.0.0.1 \
  --port 27017 \
  --username app_user \
  --authenticationDatabase app_db \
  --password \
  --drop \
  /var/backups/mongodb/app-db-backup/app_db

Once the restore is complete, you can immediately verify the result.

Verify the documents after the restore

Connect again:

 mongosh \
  "mongodb://[email protected]:27017/app_db?authSource=app_db" \
  --password

Check the current database:

 db

Expected output:

 app_db

Now list the collections:

 show collections

The following collection should reappear in the list:

 products

Check the number of documents:

 db.products.countDocuments()

Expected result:

 3

Now retrieve the records for verification:

 db.products.find(
  {},
  {
    _id: 0,
    sku: 1,
    name: 1,
    price: 1,
    stock: 1,
    active: 1
  }
).sort({ sku: 1 })

The same three documents should be returned:

 {
  sku: 'TEST-001',
  name: 'Mechanical Keyboard',
  price: 89.9,
  stock: 12,
  active: true
}
{
  sku: 'TEST-002',
  name: 'Wireless Mouse',
  price: 39.5,
  stock: 27,
  active: true
}
{
  sku: 'TEST-003',
  name: 'USB-C Dock',
  price: 119,
  stock: 5,
  active: false
}

For an additional check, retrieve a specific record:

 db.products.findOne({ sku: "TEST-003" })

If USB-C Dock is returned with its original fields, the backup was restored correctly.

This completes the full cycle:

In more detail:

The backup has now been fully verified: the data was written and exported, the original database was deleted, and then it was restored from the dump and verified again using queries.

Troubleshooting Authentication Errors

At this point, we have two users with different responsibilities: mongo_admin manages the server, while app_user works only with app_db. Therefore, most login issues can now be troubleshot systematically.

Authentication errors are usually caused by one of four factors:

  • Incorrect username;
  • Incorrect password;
  • Incorrect authSource;
  • Insufficient roles.

It is important to first identify the type of error and only then change the configuration.

What Authentication failed Means

The message: Authentication failed, means that MongoDB was unable to authenticate the user.

The most common causes are straightforward:

  • An incorrect password was entered;
  • An incorrect username was specified;
  • An incorrect authSource was selected;
  • The user was created in a different authentication database from the one used by the client.

For example, our app_user was created in:

 app_db

Therefore, the following command is correct:

 mongosh \
  "mongodb://[email protected]:27017/app_db?authSource=app_db" \
  --password

However, the following command has an issue:

 mongosh \
  "mongodb://[email protected]:27017/app_db?authSource=admin" \
  --password

MongoDB will look for app_user in admin, but no such account exists there.

The result is Authentication failed, even if the password is correct.

Why the Correct authSource Matters

authSource specifies the database where the user account is stored.

This is not necessarily the same database that the user works with.

For example, the administrative user:

 mongo_admin

is created in:

 admin

Therefore, it uses:

 authSource=admin

The application user:

 app_user

is created in:

 app_db

Therefore, it uses:

 authSource=app_db

It is helpful to distinguish between two parameters: target database ≠ authentication database

Sometimes they are the same, as with app_user.

Sometimes they are not.

For example, a user may be created in admin but have permissions for another database. In that case, the connection string will include the target database in the path and authSource=admin.

If you confuse the two, you can check the password repeatedly, but the error will not go away.

What Happens When a User Connects to the Wrong Database

It is important to distinguish between two scenarios.

The first is specifying the wrong authentication database.

For example, app_user

was created in app_db, but the client uses:

 authSource=admin

In this case, the user will fail authentication.

The second scenario is when the user is successfully authenticated but switches to a database where they do not have the required role.

For example, app_user connected using the correct setting:

 authSource=app_db

and then ran:

 use admin

Simply switching the database context does not grant the user permissions on admin.

If the following administrative command is then run:

 db.getUsers()

MongoDB should return an authorization error.

In other words, a successful login does not grant permissions on every database.

Permissions are determined by the assigned roles.

How to check a user’s roles

It is more convenient to check user details while authenticated as mongo_admin.

Connect:

 mongosh \
  --username mongo_admin \
  --authenticationDatabase admin \
  --password

To view app_user, switch to its authentication database:

 use app_db

Then run:

 db.getUser("app_user")

The output should include the following role:

 readWrite

for:

 app_db

To view a more complete list of users, run:

 db.getUsers()

To check the administrative user:

 use admin
db.getUser("mongo_admin")

This provides quick answers to two questions:

  • Which database the user was created in;
  • Which roles are assigned to the user.

If the user can log in successfully but a specific operation returns Unauthorized, the issue is usually with permissions rather than the password.

Practical Exercise: Diagnosing a Login Error

Let’s examine a typical scenario.

A user attempts to connect:

 mongosh \
  "mongodb://[email protected]:27017/app_db?authSource=admin" \
  --password

The correct password is entered, but the following error occurs:

 Authentication failed

First, check whether the user exists.

While logged in as mongo_admin:

 use app_db
db.getUser("app_user")

If the user is found, check which database we are checking for the user in.

In this case, it is:

 app_db

Therefore, the authentication database must be the same.

Correct the connection string:

 mongosh \
  "mongodb://[email protected]:27017/app_db?authSource=app_db" \
  --password

Now enter the same password.

The connection should succeed.

If it does not, verify the username:

 app_user

and manually re-enter the password.

The next scenario is when login succeeds, but an operation is denied.

For example:

 use admin
db.getUsers()

This results in an Unauthorized error.

In this case, authentication is working correctly. The app_user account simply does not have administrative roles.

Check the user’s permissions:

 use app_db
db.getUser("app_user")

If the output shows:

 readWrite

for app_db, this behavior is correct.

The main errors can be summarized in a single table:

ErrorPossible causeWhat to checkSolution
Authentication failed Incorrect passwordRe-enter the passwordUse the correct credentials
Authentication failed Incorrect usernameUsernameCorrect the username
Authentication failed Incorrect authSource Where the user was createdSpecify the correct authentication database
Unauthorized Insufficient permissionsdb.getUser() and rolesAssign the required role or use another user
Login succeeds, but an admin command is deniedThe user is not an administratorThe user’s rolesUse mongo_admin 
User not foundThe wrong database is being checkedRun use <auth_db> Switch to the correct authentication database

The key distinction here is simple:

Keeping this distinction in mind makes it possible to diagnose most login issues fairly quickly.

Troubleshooting Connection Errors

We have already covered authentication errors. Now let’s move on to another class of issues: cases where the client cannot establish a connection to mongod at all.

It is important to distinguish between diagnostic layers. If MongoDB responds with Authentication failed, the network connection is already working. By contrast, Connection refused, a timeout, or no response at all usually indicates an issue with the service, bindIp setting, port, or firewall.

What “Connection refused” Means

An error such as:

 Connection refused

usually means that the client was able to reach the specified address, but no service accepted the connection on the specified port.

The most common causes are:

  • mongod is not running;
  • MongoDB is listening on a different interface;
  • the IP address is incorrect;
  • the port is incorrect;
  • the service exited due to a configuration error.

First, check mongod itself:

 sudo systemctl status mongod

For a quick check:

 sudo systemctl is-active mongod

Expected output:

 active

If the service is stopped, try starting it:

 sudo systemctl start mongod

If it fails to start:

 sudo journalctl -u mongod -n 100 --no-pager

This is especially important after modifying mongod.conf: invalid YAML, an incorrect IP address in bindIp, or another configuration error may prevent the server from starting at all.

Why MongoDB May Listen Only on localhost

Even if mongod is running, remote connections may fail because of the following configuration:

 net:
  port: 27017
  bindIp: 127.0.0.1

With this configuration, MongoDB accepts connections only through the loopback interface.

Local connections will work:

 mongosh \
  "mongodb://[email protected]:27017/app_db?authSource=app_db" \
  --password

However, attempts to connect externally using the server’s public or private IP address will fail.

You can check the current configuration as follows:

 grep -A 4 "^net:" /etc/mongod.conf

Alternatively, check which addresses the process is actually listening on:

 sudo ss -lntp | grep 27017

If the output shows only:

 127.0.0.1:27017

MongoDB is accessible only locally.

If remote access is required, add the local address of the appropriate interface:

 net:
  port: 27017
  bindIp: 127.0.0.1,10.0.0.10

After making the change:

 sudo systemctl restart mongod

Then check again:

 sudo ss -lntp | grep 27017

How to Check Port 27017

It is easier to run diagnostics from both ends.

First, on the MongoDB VPS itself:

 sudo ss -lntp | grep 27017

This command shows whether a process is listening on TCP port 27017 and which address it is bound to.

For example:

 127.0.0.1:27017

means that it is listening only on localhost.

Whereas:

 10.0.0.10:27017

means that MongoDB accepts connections on the private network interface.

Now check the port from the Application VPS:

 nc -vz 10.0.0.10 27017

If the connection is successful, you will receive a message confirming that the TCP connection has been established.

If nc is not installed:

 sudo apt install -y netcat-openbsd

Only after the TCP test succeeds does it make sense to test mongosh.

For example:

 mongosh \
  "mongodb://[email protected]:27017/app_db?authSource=app_db" \
  --password

This makes it much easier to isolate the problem.

If nc cannot connect, the MongoDB credentials are not the issue at this stage.

How to distinguish a firewall issue from a MongoDB issue

Suppose the remote connection is not working.

First, test MongoDB locally:

 mongosh \
  "mongodb://[email protected]:27017/app_db?authSource=app_db" \
  --password

If the local connection works, this means that:

  • mongod is running;
  • authentication is working;
  • the user exists.

Next, check:

 sudo ss -lntp | grep 27017

If the required private or public IP address is listed, MongoDB is listening on an external interface.

Now check the firewall:

 sudo ufw status numbered

For our private network setup, there should be an allow rule similar to this:

10.0.0.20 → 27017/tcp

If the rule is missing:

 sudo ufw allow from 10.0.0.20 to any port 27017 proto tcp

If UFW is configured correctly but the connection still fails, check the cloud provider’s external firewall.

In other words, troubleshoot the issue step by step:

If ss shows the required address on the local server but a remote nc connection fails, the likely cause shifts to the firewall or routing.

What to Do When a Connection Times Out

A timeout is different from Connection refused.

With Connection refused, the response usually arrives quickly: the remote host reports that nothing is available to accept the connection.

With a timeout, the client sends a request but does not receive a normal response within the allotted time.

Common causes:

  • the firewall silently drops packets;
  • the cloud firewall blocks traffic;
  • an incorrect IP address is specified;
  • there is no route between the private networks;
  • the application is trying to access a private IP address from a network that cannot reach it;
  • there is an issue with the network ACL or routing.

Start by checking the IP address:

 ip addr

On the MongoDB VPS, verify that the address specified in bindIp is actually assigned to the server.

For example, if the configuration contains:

 bindIp: 127.0.0.1,10.0.0.10

the server must actually have the following address:

 10.0.0.10

Next, run the following from the Application VPS:

 nc -vz 10.0.0.10 27017

If the private network is being used for the first time, it is also useful to check the route:

 ip route

You can also inspect the path to the host:

 tracepath 10.0.0.10

However, a lack of ICMP responses does not necessarily mean that MongoDB is unreachable: some networks filter diagnostic traffic separately.

Therefore, the key test remains a TCP connection specifically to port 27017.

Connection Diagnostic Commands

When troubleshooting MongoDB, it is better to follow a short sequence of steps rather than changing settings indiscriminately.

On the MongoDB VPS:

 sudo systemctl is-active mongod

Then:

 sudo ss -lntp | grep 27017

Check the configuration:

 grep -A 4 "^net:" /etc/mongod.conf

Check UFW:

 sudo ufw status numbered

View the latest service messages:

 sudo journalctl -u mongod -n 100 --no-pager

And the MongoDB log:

 sudo tail -n 100 /var/log/mongodb/mongod.log

Now, on the Application VPS:

 nc -vz 10.0.0.10 27017

If the TCP connection works, test MongoDB itself:

 mongosh \
  "mongodb://[email protected]:27017/app_db?authSource=app_db" \
  --password

This allows you to quickly identify the exact layer at which the connection is failing.

SymptomPossible causeCommandAction
Connection refused mongod is stoppedsystemctl status mongod Start the service and check the logs
Connection refused during remote accessMongoDB is listening only on localhostss -lntp | grep 27017 Add the appropriate server IP address to bindIp 
TimeoutThe firewall is blocking trafficufw status numbered Allow access to port 27017 only from the trusted IP address
Timeout when using a private IP addressNo route exists between the serversip route Check the private network and routing
Works locally but not remotelybindIp or firewallss, ufw, nc Troubleshoot the network layer by layer
TCP works, but mongosh cannot log inAuthentication issuemongosh … --password Check the username, password, and authSource 
mongod does not start after configuration changesError in mongod.conf journalctl -u mongod Correct the configuration and restart the service

The main troubleshooting rule here is simple: first check the service and TCP connectivity, and only then check the credentials.

If port 27017 is inaccessible at the network layer, changing the password or authSource will not resolve the issue. Conversely, if the TCP connection succeeds but MongoDB returns Authentication failed, there is no need to troubleshoot the firewall.

Verifying MongoDB After a Reboot

The core configuration is now complete: MongoDB runs as a systemd service, authorization is enabled, users have been created, network access is restricted, and the data has successfully gone through a full backup and restore cycle.

One important scenario remains to be tested: what happens after a routine VPS reboot. The server should return to an operational state without requiring mongod to be started manually and without losing any configuration settings.

What Should Start Automatically

Earlier, we enabled the service to start automatically:

 sudo systemctl enable mongod

Therefore, after a reboot, systemd should automatically start:

 mongod.service

All settings from the following file should remain in effect:

 /etc/mongod.conf

Including:

 security:
  authorization: enabled

and the current net section.

In other words, after the reboot, we expect all of the following:

  • mongod is running;
  • MongoDB is listening on the required interface;
  • Authorization remains enabled;
  • The users are preserved;
  • The app_db database and the products collection remain in place;
  • The application can connect using the same connection string.

Now let’s verify this in practice.

How to check the service

Reboot the VPS:

 sudo reboot

After reconnecting via SSH, first check the status of MongoDB:

 sudo systemctl status mongod

Expected output:

 active (running)

Shorter command:

 sudo systemctl is-active mongod

Output:

 active

You can also verify that automatic startup is enabled:

 sudo systemctl is-enabled mongod

Expected output:

 enabled

If mongod does not start after the reboot, check the following:

 sudo journalctl -u mongod -b --no-pager

The option:

 -b

shows messages from the current system boot, making it easy to find errors that occurred after the reboot.

Verifying Authorization

Now verify that MongoDB has not reverted to anonymous access.

Connect without credentials:

 mongosh

In the shell, run:

 show dbs

This protected command should not run without authentication.

Now exit:

 exit

Then connect as app_user:

 mongosh \
  "mongodb://[email protected]:27017/app_db?authSource=app_db" \
  --password

The login should succeed if the password is correct.

This confirms two things:

  • authorization: enabled persisted after the reboot;
  • The app_user account remains accessible.

If necessary, you can also verify the admin account:

 mongosh \
  --username mongo_admin \
  --authenticationDatabase admin \
  --password

Verifying Data After a Reboot

Now verify that the saved data is still available.

As app_user:

 db

Expected output:

 app_db

Check the collection:

 show collections

The list should include:

 products

Now count the documents:

 db.products.countDocuments()

Expected result:

 3

Then display the verification records:

 db.products.find(
  {},
  {
    _id: 0,
    sku: 1,
    name: 1,
    stock: 1
  }
).sort({ sku: 1 })

You should see the following again:

  • TEST-001
  • TEST-002
  • TEST-003

This confirms that the data survived not only the restore but also a normal restart of the entire VPS.

You can also verify the network configuration again:

 sudo ss -lntp | grep 27017

MongoDB should be listening on the same addresses specified in mongod.conf.

If you are using a remote Application VPS, run the following from that server:

 nc -vz 10.0.0.10 27017

and then:

 mongosh \
  "mongodb://[email protected]:27017/app_db?authSource=app_db" \
  --password

The final verification can be organized into four levels:

CheckCommandExpected result
Servicesystemctl is-active mongod active 
Authmongosh … --password The user logs in successfully
Datadb.products.countDocuments() 3
Networkss -lntp | grep 27017 MongoDB is listening on the required addresses

If all four checks pass after a reboot, MongoDB automatically returns to an operational state: the service starts, authorization remains in effect, the data is preserved, and network access remains the same as before the reboot.

You can now proceed to the final section and review the key recommendations for production: how to store credentials, restrict network access, manage backups, and monitor server health.

How to Use MongoDB Safely in Production

Do Not Use an Administrator Account for the Application

mongo_admin is intended for MongoDB administration, not for the application’s day-to-day operations.

The application must connect using a separate account:

 app_user

with permissions limited to its own database:

 app_db

The reason is simple: if the application runs under an administrator account, any application error or compromise can result in excessively broad access.

The following setup is much more secure:

The passwords for these accounts must also be stored separately. Administrator credentials must not be included in the application’s .env file, deployment scripts, or CI/CD variables used by the application itself.

Do Not Expose Port 27017 to the Entire Internet

MongoDB should not become a public service simply because the application requires remote access.

If the application and MongoDB are hosted on the same VPS, it is best to keep:

 net:
  bindIp: 127.0.0.1

If they are hosted on separate servers, it is preferable to use a private network.

For example: Application VPS → 10.0.0.10:27017 → MongoDB VPS

Only if a private network is unavailable should you use a public interface, and even then, the firewall must allow connections only from a specific trusted IP address.

In other words, the undesirable configuration is: 27017/tcp → accessible to everyone

The proper configuration is: 27017/tcp → accessible only to the Application VPS

Authorization remains mandatory in all cases. A firewall does not replace users and roles; it complements them.

Limit roles

Each user should be granted only the permissions they actually need for their task.

For a typical application, we used:

 readWrite

on:

 app_db

If a separate service only needs analytics or read access, grant it the following role instead of readWrite:

 read

Do not grant root if the user only needs to work with a single database.

The more limited the permissions, the less severe the consequences of an application error, credential leak, or incorrectly written query.

To quickly review a user, periodically run:

 db.getUser("app_user")

and verify that the list of roles has not grown unnecessarily over time.

Store backups outside the MongoDB VPS

A local backup is convenient:

 /var/backups/mongodb

but it should not be the only copy.

If the VPS loses a disk, is deleted, or becomes unavailable due to a failure, the local backup will be lost along with the original data.

A production setup should therefore look something like this:

Suitable external storage options include:

  • Object Storage;
  • a dedicated backup VPS;
  • another storage system in a separate fault domain;
  • secure enterprise backup storage.

The key is not to keep the only backup copy alongside the original.

Test restores regularly

Creating a backup alone does not guarantee that the data can actually be restored.

We have already tested this manually:

For production, this check should also be performed regularly, but in a separate test environment.

Verify that:

  • the backup is readable;
  • mongorestore completes without errors;
  • the collections are present;
  • the documents are restored;
  • the indexes are restored;
  • the application can access the required data after the restore.

A good backup strategy is not “a file is created every night,” but “we know we can restore from that file.”

Monitor Disk Space and Logs

MongoDB continuously grows as data, indexes, and logs accumulate.

You should therefore monitor free space proactively rather than waiting for the file system to fill up.

For a quick check:

 df -h

Data size:

 sudo du -sh /var/lib/mongodb

Log size:

 sudo du -sh /var/log/mongodb

Latest log entries:

 sudo tail -n 100 /var/log/mongodb/mongod.log

Service status:

 sudo systemctl status mongod

It is especially important to monitor disk space before large backups, restores, and upgrades.

If very little free space remains, even a routine maintenance operation can cause problems.

Upgrade MongoDB using a supported upgrade path

Do not upgrade MongoDB across multiple major versions without first verifying compatibility.

Before upgrading, check the following:

  • The current version;
  • The target version;
  • Whether a direct upgrade is supported;
  • Whether there are any breaking changes;
  • Whether an intermediate upgrade is required;
  • Whether the application’s drivers are compatible.

You can check the current server version as follows:

 mongod --version

Before upgrading, make sure you have a recent backup and a tested restore procedure.

For production environments, follow a sequential upgrade path:

rather than attempting to skip several MongoDB generations at once.

After the upgrade, repeat the usual checks:

 sudo systemctl status mongod
mongosh \
  "mongodb://[email protected]:27017/app_db?authSource=app_db" \
  --password

and verify that the application can still access its data.

What to Check Before Production

Before the application begins using MongoDB continuously, run through these quick checks.

Access and Permissions

  • authorization is enabled;
  • the application uses a dedicated app_user;
  • app_user has no administrative roles;
  • the application does not use mongo_admin;
  • credentials are not hard-coded in commands or application code.

Network and Data

  • port 27017 is not exposed to the entire internet;
  • bindIp includes only the required server interfaces;
  • the firewall allows connections only from trusted sources;
  • MongoDB starts automatically after a reboot;
  • data can be saved and read after a reboot.

Backups and Operations

  • mongodump runs regularly;
  • backups are transferred to external storage;
  • the restore process has been tested in practice;
  • free disk space is monitored;
  • logs are reviewed when errors occur;
  • major upgrades are performed sequentially, with a backup taken before upgrading.

If these requirements are met, the basic MongoDB configuration is in good shape for a small production project: the application operates with minimal privileges, network access is restricted, and the data is backed up.

Conclusion

A standalone MongoDB instance on a single VPS is well suited for development, test environments, small internal services, and projects where manual intervention is acceptable in the event of a server failure. This setup is easy to maintain: a single mongod process, straightforward configuration, separate users, controlled network access, and standard backups created with mongodump.

However, a standalone server has a fundamental limitation: it is a single point of failure. If the VPS or mongod itself is unavailable, the application loses access to the database until the service is restored. Therefore, for a full-fledged production system where high availability and automatic failover are important, it is worth switching to a replica set. A self-managed deployment typically consists of several MongoDB nodes. If you do not want to handle fault tolerance, updates, monitoring, and backups yourself, you can consider managed MongoDB. A replica set provides redundancy and automatic failover, whereas a standalone server does not. 

Regardless of the architecture, the core principles remain the same: do not use an administrative user in the application, do not expose port 27017 unless necessary, restrict roles, store backups separately from the primary server, and periodically test the restore process. Following these practices keeps even a small MongoDB deployment predictable to operate and makes failures significantly easier to diagnose.

FAQ

Is it necessary to enable authentication if MongoDB is accessible only from localhost?

The risk is indeed lower in a local test environment because mongod bound to 127.0.0.1 does not accept remote connections.

However, it is still best to enable authentication on a production server. Otherwise, a local process, a compromised application, or another system user could access MongoDB without having to provide separate credentials.

Furthermore, if remote access is needed later, the database will already be protected, and there will be no need to change the security model on a live server.

Can the same user account be used for multiple applications?

Technically, yes—if the applications use the same database and require the same permissions.

However, separate accounts are usually more convenient.

For example:

 backend_user
analytics_user
worker_user

This makes it easier to:

  • assign different roles;
  • change the password for a single application;
  • disable an individual service;
  • determine which credentials are used where and who changed or deleted what.

If a shared password is compromised, it must be changed in every application at once.

What Is authSource For?

authSource specifies the database in which MongoDB should look for the user account.

For example, if:

 app_user

was created in:

 app_db

then use:

 authSource=app_db

If mongo_admin was created in admin:

 authSource=admin

The working database and the authentication database do not have to be the same.

Therefore, an incorrect authSource can cause an Authentication failed error even if the username and password are correct.

Can mongodump be run without stopping MongoDB?

Yes. mongodump connects to a running mongod process, so there is no need to stop the server for a standard dump.

However, there is one caveat: if writes continue during the backup, a dump of an individual database or collection may not represent a single point in time. For heavily loaded systems and strict consistency requirements, consider the write patterns and use an appropriate backup strategy. Additional oplog-based mechanisms are available for replica sets.

What happens if you run mongorestore against an existing database?

Without --drop, the utility attempts to restore data into the existing collections.

This can result in:

  • _id conflicts;
  • a mix of old and restored data;
  • a result that differs from the state of the backup.

To replace the corresponding collections with the contents of the dump, use:

 mongorestore --drop ...

Before restoring, --drop removes only the collections that will subsequently be restored from the backup. This option does not by itself remove collections that are absent from the dump. 

Does mongodump preserve users?

It depends on how the dump is created.

When backing up a specific database using --db, you can include user and role definitions with the following option:

 --dumpDbUsersAndRoles

When dumping the entire instance, user and role definitions are included automatically.

Therefore, you should not assume that every single-database dump includes its users by default.

Can I back up just one collection?

Yes.

For example:

 mongodump \
  --db app_db \
  --collection products \
  --out /var/backups/mongodb/products-backup

This way, the dump will contain only products, rather than the entire app_db. MongoDB

This approach is useful for selectively migrating or backing up specific data, but fully restoring the application requires a clear understanding of the dependencies between collections.

Why does mongosh connect locally but not from another server?

If local connections work but remote connections do not, first check:

 sudo ss -lntp | grep 27017

If MongoDB is listening only on:

 127.0.0.1:27017

the remote server will not be able to connect.

Next, check:

  • bindIp;
  • UFW;
  • cloud firewall;
  • private network;
  • the route between the VPS instances.

In other words, a successful local mongosh connection does not necessarily mean that mongod is accepting connections on an external interface.

What should you do if the admin password is lost after enabling authorization?

First, rule out the obvious causes:

  • an incorrect username;
  • an incorrect authSource;
  • different saved admin user credentials;
  • an error when entering the password.

If no valid administrative credentials remain, a separate administrative access recovery procedure is required. This involves making controlled changes to the MongoDB configuration by disabling authentication, ensuring that MongoDB is not externally accessible, and creating or modifying a user.

In production, it is best not to improvise on a live server. Before taking these steps, create a backup, restrict network access, and follow the recovery procedure appropriate for the installed MongoDB version.

Is mongodump sufficient for production?

mongodump is useful for small databases and certain backup scenarios, but it is not a universal solution for every production system.

For large data volumes, a dump can generate significant load, and during active writes, backup consistency must be considered separately. A replica set also provides additional options for obtaining a consistent copy using the oplog. 

Therefore, a production backup solution should be selected based on:

  • database size;
  • write frequency;
  • acceptable data loss;
  • required recovery time;
  • standalone or replica set architecture;
  • available external storage.

Most importantly, any chosen backup method must be regularly validated through actual restore tests.

Sources

  1. MongoDB Docs — Install MongoDB Community Edition on Ubuntu
  2. MongoDB Docs — Enable Access Control on Self-Managed Deployments
  3. MongoDB Docs — Configure MongoDB with the Self-Managed Configuration File
  4. MongoDB Database Tools — mongodump
  5. MongoDB Database Tools — mongorestore

Subscribe to our newsletter and receive articles and news

    Check out our other materials