
If you’ve just spun up a fresh Ubuntu 26.04 server and you’re staring at the terminal wondering why apt install mongodb isn’t giving you what you expected, you’re not alone. Ubuntu’s default repositories ship an outdated, community-maintained MongoDB package that Canonical stopped syncing with upstream years ago. Anyone who’s tried to run a modern application stack on that ancient build knows the pain: missing aggregation features, deprecated authentication mechanisms, and compatibility headaches with drivers built for MongoDB 6.0 and beyond.
This guide walks through installing MongoDB 8.0 (the current stable branch as of this writing) directly from MongoDB’s official APT repository on Ubuntu 26.04, the same way it would be done on a production box handling real traffic. There’s a difference between following a quick copy-paste tutorial and actually understanding what each step does to your system, and that difference matters the first time something breaks at 2 AM.
Since Ubuntu 26.04 was only recently released, MongoDB’s package repository hasn’t published a codename-specific plucky or 26.04-tagged channel yet. That’s not unusual. Debian and Ubuntu-based database vendors typically lag behind distro releases by several months while they validate compatibility against newer glibc and OpenSSL versions. The practical workaround, which is also what MongoDB’s own documentation recommends during this transition window, is to use the noble (24.04) repository line, since Ubuntu 26.04 remains binary-compatible with it for MongoDB’s purposes. This isn’t a hack; it’s standard practice and something you’ll see repeated across Debian point-release gaps too.
By the end of this article you’ll have a hardened, systemd-managed MongoDB instance running with authentication enabled, a properly configured firewall, and enough troubleshooting knowledge to handle the errors that actually show up in production rather than the sanitized ones in most tutorials.
Before You Start: System Requirements and Preparation
MongoDB 8.0 requires a 64-bit system, and it officially supports x86_64 and ARM64 architectures. Before touching the package manager, confirm your kernel and architecture align with what MongoDB expects.
uname -m
lsb_release -a
You want x86_64 or aarch64 output, and confirmation that you’re indeed on Ubuntu 26.04. If you’re running this inside a container or a minimal cloud image, some base utilities like gnupg and curl might not be present. Skipping this check is one of the most common reasons people hit a wall on the very first command.
sudo apt update
sudo apt install -y gnupg curl
Memory matters more than people expect with MongoDB. The WiredTiger storage engine caches roughly 50% of (RAM minus 1GB) by default, so on a 2GB VPS you’re looking at a cache ceiling of around 500MB. That’s fine for development or light testing, but if you’re planning to run this in production with any meaningful dataset, budget at least 4GB of RAM and preferably SSD-backed storage. Disk I/O latency is one of the top culprits behind slow MongoDB queries, and spinning disks under concurrent write load will bottleneck you long before CPU does.
Step 1: Import the MongoDB GPG Key
MongoDB signs its packages, and Ubuntu’s apt refuses to install anything from an untrusted source without a valid signature. Modern Ubuntu releases have also deprecated apt-key, so the correct approach is to store the key directly as a keyring file.
curl -fsSL https://www.mongodb.org/static/pgp/server-8.0.asc | \
sudo gpg -o /usr/share/keyrings/mongodb-server-8.0.gpg --dearmor
A quick note here: if you’ve inherited a server from someone who followed an older guide, check for leftover apt-key add entries first. Mixing the legacy trusted keyring with the newer signed-by method is a frequent source of “NO_PUBKEY” errors down the line, and cleaning that up after the fact is more annoying than doing it right the first time.
Step 2: Add the MongoDB APT Repository
Create the repository list file, pointing it at the noble branch since that’s the currently validated line for MongoDB 8.0 on recent Ubuntu releases.
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
If you’re on ARM64 hardware, such as a Graviton instance on AWS or an Ampere-based VPS, this same line works because the arch=amd64,arm64 declaration already covers both. No separate repo file needed.
Refresh your package index immediately after this:
sudo apt update
If this command throws a 404 or signature mismatch, don’t panic and don’t start deleting files randomly. Nine times out of ten it’s a stale cache or a typo in the codename. Double-check the file contents with cat /etc/apt/sources.list.d/mongodb-org-8.0.list before assuming the repository itself is broken.
Step 3: Install MongoDB Packages
sudo apt install -y mongodb-org
This metapackage pulls in mongodb-org-server, mongodb-org-mongos, mongodb-org-tools, and mongodb-mongosh, which together give you the daemon, the sharding router, backup/restore utilities, and the modern shell client. If you need version pinning for reproducibility across a fleet of servers (and you should, if you’re managing more than one), install explicit versions instead:
sudo apt install -y mongodb-org=8.0.20 mongodb-org-database=8.0.20 mongodb-org-server=8.0.20 mongodb-mongosh mongodb-org-mongos=8.0.20 mongodb-org-tools=8.0.20
Pinning versions this way also protects you from apt upgrade silently jumping a major version during a routine maintenance window, which has bitten more than a few teams who assumed minor version bumps were always safe.
To prevent accidental upgrades entirely, hold the packages:
sudo apt-mark hold mongodb-org mongodb-org-database mongodb-org-server mongodb-org-mongos mongodb-org-tools mongodb-mongosh
This is standard practice on any production database host. You want to control when major version upgrades happen, not have unattended-upgrades decide for you.
Step 4: Start and Enable the MongoDB Service
Ubuntu 26.04 uses systemd, so service management is straightforward.
sudo systemctl start mongod
sudo systemctl enable mongod
sudo systemctl status mongod
You’re looking for active (running) in green. If the status shows failed right out of the gate, resist the urge to just restart it blindly. Check the logs first:
sudo journalctl -u mongod --no-pager -n 50
or the dedicated log file:
sudo tail -n 50 /var/log/mongodb/mongod.log
The vast majority of first-boot failures trace back to either a permissions mismatch on /var/lib/mongodb or a leftover lock file from an interrupted install. More on that in the troubleshooting section below.
Step 5: Verify the Installation
Connect using the modern shell:
mongosh
Once inside, confirm the version and run a basic sanity check:
db.version()
db.runCommand({ connectionStatus: 1 })
If you get a prompt and a version string matching what you installed, the core server is functioning correctly. This is also a good moment to create a test database and insert a document just to confirm write operations complete without error, since a server that starts but can’t write to disk is a subtly different problem than one that won’t start at all.
Step 6: Configure MongoDB for Real-World Use
The default configuration file lives at /etc/mongod.conf, and out of the box it binds only to 127.0.0.1. That’s actually the correct default for security reasons, but it means nothing outside localhost can reach it, which trips people up constantly when they deploy MongoDB on one server and their application on another.
Open the config:
sudo nano /etc/mongod.conf
To allow remote connections (only do this if you understand the security implications and have a firewall in place):
net:
port: 27017
bindIp: 127.0.0.1,10.0.0.15
Never bind to 0.0.0.0 on a public-facing server without authentication and firewall rules already locked down. This is one of the most common causes of ransomware attacks against exposed MongoDB instances, and it’s entirely preventable.
While you’re in the config file, it’s worth adjusting a few other settings for production workloads. The storage.wiredTiger.engineConfig.cacheSizeGB value is worth setting explicitly rather than relying on the automatic calculation, especially on shared hosting environments or containers where MongoDB might misread the available memory:
storage:
dbPath: /var/lib/mongodb
wiredTiger:
engineConfig:
cacheSizeGB: 2
Restart the service after any config change:
sudo systemctl restart mongod
Enabling Authentication (Don’t Skip This)
A shocking number of exposed, unauthenticated MongoDB instances still get discovered by automated scanners within minutes of being spun up. This isn’t theoretical; Shodan searches for open MongoDB ports return tens of thousands of results at any given time, and a meaningful chunk of them have zero authentication.
First, create an admin user while the server is still running without auth enforced:
use admin
db.createUser({
user: "dbAdmin",
pwd: passwordPrompt(),
roles: [ { role: "userAdminAnyDatabase", db: "admin" }, "readWriteAnyDatabase" ]
})
Using passwordPrompt() instead of typing the password inline keeps it out of your shell history, which matters more than people think until they’ve had a password leak into a bash history file that got backed up somewhere unexpected.
Now enable authorization in the config file:
security:
authorization: enabled
Restart the service, then reconnect using credentials:
sudo systemctl restart mongod
mongosh -u dbAdmin -p --authenticationDatabase admin
From here on, every connection to this instance requires valid credentials. Set up application-specific users with narrowly scoped roles rather than reusing the admin account across services. A read-only analytics dashboard has no business holding write privileges on your production collections.
Firewall and Network Hardening
If MongoDB needs to accept connections from other machines, configure ufw explicitly rather than opening the port to the world.
sudo ufw allow from 10.0.0.0/24 to any port 27017
sudo ufw enable
For cloud environments like AWS or DigitalOcean, mirror this at the security group or VPC firewall level too. Defense in depth means the host firewall and the cloud-level firewall both need to agree before traffic reaches the database.
If you’re running MongoDB behind a reverse proxy or application server on the same host, there’s a strong argument for binding MongoDB exclusively to 127.0.0.1 and never opening 27017 externally at all. The application talks to MongoDB locally, and nothing outside the box ever needs a direct line to the database. This single decision eliminates an entire category of attack surface.
Performance Tuning: CPU, Memory, Disk, and Network
Once MongoDB is running, the next phase is making sure it performs well under real load, not just synthetic benchmarks.
Disk I/O
MongoDB is disk-intensive by nature, particularly with journaling enabled (which you should never disable in production). Use iostat -x 1 during peak load to check for high %util or elevated await times. If you’re seeing sustained disk queue depth issues, that’s your signal to move to NVMe storage or, at minimum, provisioned IOPS volumes if you’re on cloud infrastructure.
Also disable atime updates on the MongoDB data partition, since they add unnecessary write overhead for no real benefit:
/dev/sdb1 /var/lib/mongodb ext4 defaults,noatime 0 2
Memory and Swappiness
Set vm.swappiness low on database servers, since you want the kernel to avoid swapping MongoDB’s working set out to disk under memory pressure.
sudo sysctl vm.swappiness=1
echo "vm.swappiness=1" | sudo tee -a /etc/sysctl.conf
Also disable Transparent Huge Pages (THP), which is a well-documented performance killer for WiredTiger:
echo never | sudo tee /sys/kernel/mm/transparent_hugepage/enabled
echo never | sudo tee /sys/kernel/mm/transparent_hugepage/defrag
Make this persistent across reboots with a systemd service or an entry in /etc/rc.local, since it resets on every restart otherwise.
Connection and Query Optimization
Set appropriate connection pool limits on your application side rather than letting drivers default to overly aggressive pool sizes that can overwhelm the server during traffic spikes. Use db.currentOp() to inspect long-running operations, and enable the profiler temporarily during suspected slowdowns:
db.setProfilingLevel(1, { slowms: 100 })
This logs any operation taking longer than 100ms, giving you concrete data instead of guesswork when diagnosing a slow endpoint.
Common Errors and How to Actually Fix Them
“E: The repository ‘https://repo.mongodb.org/apt/ubuntu noble/mongodb-org/8.0 Release’ does not have a Release file.”
This almost always means a typo in the codename or architecture declaration inside the .list file. Re-check the exact string against what’s shown above, and confirm there’s no trailing whitespace or duplicate entry from a previous install attempt.
mongod fails to start with “Failed to unlink socket file /tmp/mongodb-27017.sock”
This happens after an unclean shutdown. Manually remove the stale socket:
sudo rm /tmp/mongodb-27017.sock
sudo systemctl start mongod
“child process failed, exited with error number 14”
This is almost always a permissions issue on the data directory. Fix ownership:
sudo chown -R mongodb:mongodb /var/lib/mongodb
sudo chown -R mongodb:mongodb /var/log/mongodb
Connection refused when connecting from another host
Check three things in order: whether bindIp in mongod.conf includes the correct interface, whether ufw (or your cloud firewall) allows the port, and whether the service is actually listening on the expected interface using sudo ss -tlnp | grep 27017.
Out of memory killer terminating mongod under load
Check dmesg | grep -i "killed process" to confirm the OOM killer is the culprit. This usually means the WiredTiger cache size wasn’t adjusted for the available RAM, or another memory-hungry process is competing for resources on the same box. Either resize the instance or explicitly cap the cache size as shown earlier.
Backup Strategy Before You Go Live
None of the above matters if there’s no backup plan. Use mongodump for logical backups on smaller datasets:
mongodump --uri="mongodb://dbAdmin:yourpassword@localhost:27017" --out=/backups/$(date +%F)
For larger production datasets, filesystem-level snapshots (via LVM or your cloud provider’s snapshot feature) combined with journaling give you a more consistent, faster recovery path. Automate this with a cron job and, critically, actually test the restore process periodically. A backup nobody has ever restored is a backup you don’t actually have.