15%

Save 15% on All Hosting Services

Test your skills and get Discount on any hosting plan

Use code:

Skills
Get Started
23.10.2024

How to Install and Configure MongoDB on a VPS (Complete Guide)

MongoDB is a document-oriented NoSQL database that stores records as BSON (Binary JSON) documents, enabling schema-free data modeling with horizontal scalability through native sharding. Unlike relational databases, MongoDB requires no predefined table schema, making it the dominant choice for applications with evolving data structures, high write throughput, or hierarchical data relationships.

This guide walks through a production-grade MongoDB deployment on a Linux VPS — covering installation from the official repository, authentication hardening, network access control, TLS configuration, performance tuning, and backup automation. Every step assumes you are operating in a real server environment where security and reliability are non-negotiable.

Prerequisites

Before proceeding, confirm the following:

  • A VPS running Ubuntu 20.04 LTS or Ubuntu 22.04 LTS (commands are identical for both)
  • Root or sudo-privileged user access via SSH
  • A minimum of 2 GB RAM (4 GB recommended for production workloads)
  • At least 20 GB of available disk space on a fast storage volume
  • UFW or iptables available for firewall management
  • Basic familiarity with the Linux command line

> Architecture note: MongoDB's WiredTiger storage engine uses a default internal cache of 50% of (RAM – 1 GB). On a 2 GB VPS, that yields roughly 512 MB of cache. For read-heavy workloads, provision at least 4 GB RAM to avoid constant disk I/O from cache pressure.

MongoDB vs. Other NoSQL Databases: Quick Comparison

FeatureMongoDBRedisCassandraCouchDB
Data modelDocument (BSON)Key-valueWide-columnDocument (JSON)
Query languageMQL (rich queries)CommandsCQLMango / MapReduce
Horizontal scalingNative shardingCluster modeNativeMulti-master
ACID transactionsYes (v4.0+, multi-doc)Partial (Lua scripts)LightweightYes
Best use caseGeneral-purpose apps, APIsCaching, sessionsTime-series, IoTOffline-first sync
Disk persistencePrimary storeOptional (RDB/AOF)Primary storePrimary store
Full-text searchAtlas Search / text indexLimitedNoLimited

Step 1: Update the System

Always begin with a fully patched system. Outdated packages introduce known CVEs that can be exploited before you even install your application stack.

sudo apt update && sudo apt upgrade -y

After applying kernel or libc updates, reboot to activate the new kernel:

sudo reboot

Reconnect via SSH after the server comes back online (typically 30–60 seconds).

Step 2: Install MongoDB from the Official Repository

Ubuntu's default apt repositories ship an outdated, community-repackaged version of MongoDB that lacks recent security patches and engine improvements. Always install from MongoDB's official repository.

Add the MongoDB GPG Key and Repository

The apt-key command is deprecated on Ubuntu 22.04. Use the recommended keyring method, which works on both 20.04 and 22.04:

curl -fsSL https://www.mongodb.org/static/pgp/server-7.0.asc | 
  sudo gpg --dearmor -o /usr/share/keyrings/mongodb-server-7.0.gpg

Add the official repository entry:

echo "deb [ arch=amd64,arm64 signed-by=/usr/share/keyrings/mongodb-server-7.0.gpg ] 
  https://repo.mongodb.org/apt/ubuntu $(lsb_release -cs)/mongodb-org/7.0 multiverse" | 
  sudo tee /etc/apt/sources.list.d/mongodb-org-7.0.list

> Version note: Replace 7.0 with your target release (e.g., 6.0) if you require a specific version for application compatibility. MongoDB 7.0 is the current Long-Term Support release as of 2024.

Install MongoDB Packages

sudo apt update
sudo apt install -y mongodb-org

This installs the following components:

    mongod — the primary database daemon
    mongos — the sharding router (used in sharded cluster deployments)
    mongosh — the modern MongoDB Shell (replaces the legacy mongo binary)
    mongodb-database-tools — includes mongodump, mongorestore, mongoexport, and mongoimport

    Pin the Installed Version

    Prevent unintended upgrades that could break application compatibility:

    echo "mongodb-org hold" | sudo dpkg --set-selections
    echo "mongodb-org-database hold" | sudo dpkg --set-selections
    echo "mongodb-org-server hold" | sudo dpkg --set-selections
    echo "mongosh hold" | sudo dpkg --set-selections
    echo "mongodb-org-mongos hold" | sudo dpkg --set-selections
    echo "mongodb-org-tools hold" | sudo dpkg --set-selections

    Step 3: Configure System-Level Prerequisites

    MongoDB performs best when certain kernel and filesystem parameters are tuned before the daemon starts.

    Set the ulimit for Open Files

    MongoDB requires a high file descriptor limit. Create a systemd override:

    sudo mkdir -p /etc/systemd/system/mongod.service.d
    sudo tee /etc/systemd/system/mongod.service.d/limits.conf > /dev/null <<EOF
    [Service]
    LimitFNOFILE=64000
    LimitNPROC=64000
    EOF

    Disable Transparent Huge Pages (THP)

    THP causes significant latency spikes in MongoDB. Disable it persistently:

    sudo tee /etc/systemd/system/disable-thp.service > /dev/null <<EOF
    [Unit]
    Description=Disable Transparent Huge Pages (THP)
    DefaultDependencies=no
    After=sysinit.target local-fs.target
    Before=mongod.service
    
    [Service]
    Type=oneshot
    ExecStart=/bin/sh -c 'echo never | tee /sys/kernel/mm/transparent_hugepage/enabled > /dev/null'
    ExecStart=/bin/sh -c 'echo never | tee /sys/kernel/mm/transparent_hugepage/defrag > /dev/null'
    
    [Install]
    WantedBy=basic.target
    EOF
    
    sudo systemctl daemon-reload
    sudo systemctl enable --now disable-thp

    Verify the setting took effect:

    cat /sys/kernel/mm/transparent_hugepage/enabled

    The output should show [never] as the active value.

    Step 4: Start and Enable MongoDB

    sudo systemctl daemon-reload
    sudo systemctl start mongod
    sudo systemctl enable mongod

    Confirm the daemon is running:

    sudo systemctl status mongod

    Look for Active: active (running) in the output. If the service fails to start, inspect the log immediately:

    sudo tail -50 /var/log/mongodb/mongod.log

    Common startup failures include:

    • Port 27017 already in use — another process is bound to the port; identify it with sudo ss -tlnp | grep 27017
    • Data directory permissions — the mongod user must own /var/lib/mongodb; fix with sudo chown -R mongodb:mongodb /var/lib/mongodb
    • THP still enabled — the WiredTiger engine logs a warning and may degrade performance

    Step 5: Secure MongoDB — Authentication and Authorization

    This is the most critical section. Unprotected MongoDB instances exposed to the internet have been responsible for thousands of data breaches. The default installation has no authentication, meaning anyone who can reach port 27017 has full read/write access to every database.

    Create the Administrative User

    Connect to the local MongoDB shell (no authentication required before enabling it):

    mongosh

    Inside the shell, switch to the admin database and create a superuser:

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

    Using passwordPrompt() instead of a plaintext string prevents the password from appearing in shell history. Type the password when prompted, then exit:

    exit

    Enable Authentication in mongod.conf

    Open the MongoDB configuration file:

    sudo nano /etc/mongod.conf

    Locate the security section (it will be commented out) and enable authorization:

    security:
      authorization: enabled

    Save and exit (Ctrl+X, then Y, then Enter), then restart the daemon:

    sudo systemctl restart mongod

    Verify Authentication Is Enforced

    Attempt an unauthenticated connection — it should now fail:

    mongosh --eval "db.adminCommand({ listDatabases: 1 })"

    You should receive an Unauthorized error. Now authenticate properly:

    mongosh -u adminuser -p --authenticationDatabase admin

    Create Application-Scoped Users

    Never use the admin superuser for application connections. Create a least-privilege user for each application database:

    use myappdb
    
    db.createUser({
      user: "appuser",
      pwd: passwordPrompt(),
      roles: [
        { role: "readWrite", db: "myappdb" }
      ]
    })

    Step 6: Configure Network Binding and Firewall Rules

    Restrict or Expand bindIp

    By default, mongod.conf binds only to 127.0.0.1. This is the correct setting if your application runs on the same VPS. If you need remote access (e.g., from an application server on a separate host), edit /etc/mongod.conf:

    net:
      port: 27017
      bindIp: 127.0.0.1,10.0.0.5

    Replace 10.0.0.5 with the specific private IP of your application server. Never set bindIp: 0.0.0.0 on a public-facing interface without a firewall rule restricting access to known IPs. Binding to all interfaces with no firewall is the leading cause of MongoDB data exposure incidents.

    Restart after changes:

    sudo systemctl restart mongod

    Configure UFW Firewall Rules

    If remote access is required, allow only the specific trusted IP:

    sudo ufw allow from 10.0.0.5 to any port 27017 proto tcp
    sudo ufw enable
    sudo ufw status verbose

    Block all other external access to port 27017:

    sudo ufw deny 27017

    UFW processes rules in order — the specific allow from rule above the broad deny rule takes precedence for the trusted IP.

    Step 7: Enable TLS/SSL for Encrypted Connections

    For any deployment where MongoDB traffic crosses a network — even a private LAN — TLS encryption is mandatory. Without it, credentials and data are transmitted in plaintext.

    Generate a self-signed certificate for testing (use a CA-signed certificate in production — consider pairing this with an SSL Certificate for your domain):

    sudo mkdir -p /etc/mongodb/ssl
    sudo openssl req -newkey rsa:4096 -nodes -keyout /etc/mongodb/ssl/mongodb.key 
      -x509 -days 365 -out /etc/mongodb/ssl/mongodb.crt 
      -subj "/CN=your-vps-hostname"
    sudo cat /etc/mongodb/ssl/mongodb.crt /etc/mongodb/ssl/mongodb.key | 
      sudo tee /etc/mongodb/ssl/mongodb.pem > /dev/null
    sudo chown -R mongodb:mongodb /etc/mongodb/ssl
    sudo chmod 600 /etc/mongodb/ssl/mongodb.pem

    Add TLS configuration to /etc/mongod.conf:

    net:
      port: 27017
      bindIp: 127.0.0.1
      tls:
        mode: requireTLS
        certificateKeyFile: /etc/mongodb/ssl/mongodb.pem

    Restart MongoDB and connect with TLS:

    sudo systemctl restart mongod
    mongosh --tls --tlsCertificateKeyFile /etc/mongodb/ssl/mongodb.pem 
      --tlsAllowInvalidCertificates -u adminuser -p --authenticationDatabase admin

    The --tlsAllowInvalidCertificates flag is only acceptable for self-signed certificates in development. Remove it when using a CA-signed certificate.

    Step 8: Performance Tuning in mongod.conf

    For a production deployment on a VPS with dedicated resources, tune the WiredTiger cache and journaling settings. Open /etc/mongod.conf and add or modify the following:

    storage:
      dbPath: /var/lib/mongodb
      journal:
        enabled: true
      wiredTiger:
        engineConfig:
          cacheSizeGB: 1.5
    
    operationProfiling:
      slowOpThresholdMs: 100
      mode: slowOp
    
    replication:
      oplogSizeMB: 1024

    Key tuning parameters explained:

    • cacheSizeGB — Set this to approximately 50% of available RAM minus 1 GB. On a 4 GB VPS, use 1.5. On an 8 GB VPS, use 3.5.
    • slowOpThresholdMs — Queries exceeding this threshold (in milliseconds) are logged to the profiler. Lowering this helps identify unindexed queries early.
    • oplogSizeMB — Relevant if you plan to add replica set members later. Pre-sizing the oplog avoids replication lag on high-write workloads.

    Apply changes:

    sudo systemctl restart mongod

    Step 9: Backup and Restore with mongodump

    Manual Backup

    mongodump 
      --uri="mongodb://adminuser:yourpassword@127.0.0.1:27017/?authSource=admin" 
      --out /var/backups/mongodb/$(date +%Y-%m-%d)

    Manual Restore

    mongorestore 
      --uri="mongodb://adminuser:yourpassword@127.0.0.1:27017/?authSource=admin" 
      /var/backups/mongodb/2024-06-15

    Automate Backups with Cron

    Create a dedicated backup script:

    sudo tee /usr/local/bin/mongodb-backup.sh > /dev/null <<'EOF'
    #!/bin/bash
    BACKUP_DIR="/var/backups/mongodb"
    TIMESTAMP=$(date +%Y-%m-%d_%H-%M-%S)
    MONGO_URI="mongodb://adminuser:yourpassword@127.0.0.1:27017/?authSource=admin"
    RETENTION_DAYS=7
    
    mkdir -p "${BACKUP_DIR}/${TIMESTAMP}"
    mongodump --uri="${MONGO_URI}" --out="${BACKUP_DIR}/${TIMESTAMP}"
    find "${BACKUP_DIR}" -maxdepth 1 -type d -mtime +${RETENTION_DAYS} -exec rm -rf {} ;
    EOF
    
    sudo chmod +x /usr/local/bin/mongodb-backup.sh

    Schedule it to run daily at 2:00 AM:

    (crontab -l 2>/dev/null; echo "0 2 * * * /usr/local/bin/mongodb-backup.sh >> /var/log/mongodb-backup.log 2>&1") | crontab -

    > Production consideration: Store backups off-server. Keeping backups on the same VPS as the database provides no protection against disk failure or server compromise. Use rsync, rclone, or an S3-compatible object store to replicate backups to a remote location.

    Step 10: Monitor MongoDB Health

    Built-in Monitoring Commands

    Inside mongosh, run server statistics:

    db.serverStatus()
    db.stats()
    db.currentOp()

    Use mongostat and mongotop

    From the shell, monitor real-time operation counts:

    mongostat --uri="mongodb://adminuser:yourpassword@127.0.0.1:27017/?authSource=admin"

    Monitor per-collection read/write time:

    mongotop --uri="mongodb://adminuser:yourpassword@127.0.0.1:27017/?authSource=admin"

    Key Metrics to Watch

    MetricWarning ThresholdWhat It Indicates
    wiredTiger.cache.bytes currently in cache> 90% of cacheSizeGBCache pressure; increase RAM or reduce dataset
    connections.current> 80% of connections.availableConnection pool exhaustion; tune app pooling
    opcounters.getmoreConsistently highCursor inefficiency; review query patterns
    repl.lag (replica sets)> 10 secondsReplication lag; check network and disk I/O
    locks.Global.acquireWaitCountAny sustained valueLock contention; review long-running operations

    Choosing the Right Hosting for MongoDB

    The performance and reliability of your MongoDB instance are directly tied to the underlying infrastructure. Consider these deployment tiers:

    • Development and staging: A standard VPS with 2–4 GB RAM is sufficient for non-production workloads, schema testing, and integration environments.
    • Production single-node: A VPS with 4–8 GB RAM, NVMe storage, and a dedicated CPU core handles moderate production traffic for most web applications.
    • High-throughput production: A Dedicated Server eliminates the noisy-neighbor effect inherent in virtualized environments. WiredTiger's I/O patterns benefit significantly from bare-metal NVMe arrays.
    • ML/analytics workloads: If you are running MongoDB alongside data pipelines, aggregation-heavy analytics, or vector search, GPU Hosting can accelerate downstream processing tasks.

    For deployments that require a graphical management interface, VPS with cPanel provides a familiar environment for teams less comfortable with pure CLI administration, though direct mongod.conf editing remains necessary for advanced configuration.

    Deployment Decision Matrix

    Use this checklist before going live:

    • [ ] MongoDB installed from the official repository, version pinned
    • [ ] mongod service enabled and confirmed active (running)
    • [ ] Transparent Huge Pages disabled and verified
    • [ ] ulimit for file descriptors set to 64000 or higher
    • [ ] Authentication enabled in mongod.conf (authorization: enabled)
    • [ ] Admin user created with passwordPrompt() — no plaintext passwords in shell history
    • [ ] Application-specific users created with least-privilege roles
    • [ ] bindIp restricted to localhost or specific trusted IPs only
    • [ ] UFW rules in place — port 27017 blocked from public internet
    • [ ] TLS enabled with a valid certificate
    • [ ] WiredTiger cache sized to 50% of (RAM – 1 GB)
    • [ ] Slow query profiling enabled (slowOpThresholdMs: 100)
    • [ ] Automated daily backups with off-server replication
    • [ ] Backup restore tested — a backup you have never restored is not a backup

    FAQ

    What is the default port MongoDB listens on, and should it be changed?

    MongoDB listens on TCP port 27017 by default. Changing it to a non-standard port adds minor obscurity but is not a substitute for authentication and firewall rules. If you change it, update net.port in /etc/mongod.conf and adjust all UFW rules and connection strings accordingly.

    Why does MongoDB use so much RAM even with a small dataset?

    WiredTiger pre-allocates its internal cache based on the formula max(50% of (RAM - 1 GB), 256 MB). This is intentional — keeping working data in memory eliminates disk reads. If RAM consumption is a concern on a small VPS, explicitly set cacheSizeGB in /etc/mongod.conf to a lower value.

    Can I run MongoDB on shared hosting?

    No. MongoDB requires a persistent background daemon (mongod), direct filesystem access to its data directory, and the ability to bind to a network port. None of these are available on Shared Web Hosting. A VPS is the minimum viable environment.

    What is the difference between mongodump and a filesystem snapshot for backups?

    mongodump performs a logical backup — it reads documents through the MongoDB query interface and exports them as BSON files. It is portable and works across versions but is slower and cannot guarantee point-in-time consistency on a live, high-write instance without --oplog. A filesystem snapshot (LVM, ZFS, or cloud block storage snapshot) captures the raw data files at a consistent point in time and is significantly faster for large datasets, but requires the storage engine to be in a consistent state.

    How do I check which MongoDB version is installed?

    Run the following command from the terminal:

    mongod --version

    Or from inside mongosh:

    db.version()
    15%

    Save 15% on All Hosting Services

    Test your skills and get Discount on any hosting plan

    Use code:

    Skills
    Get Started