Secure, Production-Grade MongoDB Installation on Ubuntu 22.04
Open MongoDB to the public internet—find yourself on a Shodan report. Install from Ubuntu defaults—risk running an unsupported version for years. Here’s how to build a stable, locked-down, and supportable MongoDB stack on Ubuntu 22.04. No shortcuts, no unnecessary exposure.
Why Not Rely on Ubuntu's Default MongoDB Packages?
Canonical's repositories distribute a MongoDB version that rapidly becomes dated—missing security patches and features introduced in 6.0+. More critically, default installations often skip rigorous, production-hardened configuration: unrestricted bind addresses, no RBAC, and insufficient resource limits. In production, these are unacceptable.
Prerequisites
- Ubuntu 22.04 LTS, patched to current
sudo
access (never run the database as root)- Comfort with CLI and editing YAML
- Ideally, a non-root
mongodb
user (created automatically below)
1. Import MongoDB GPG Key
APT must verify package signatures. MongoDB 6.0 uses its own key:
wget -qO - https://pgp.mongodb.com/server-6.0.asc | sudo tee /usr/share/keyrings/mongodb-server-6.0.gpg >/dev/null
Check for errors (key file should exist and not be empty).
2. Add Official MongoDB Repository
Set up the repository for the jammy release (22.04 LTS):
echo "deb [ arch=amd64 signed-by=/usr/share/keyrings/mongodb-server-6.0.gpg ] https://repo.mongodb.org/apt/ubuntu jammy/mongodb-org/6.0 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-6.0.list
sudo apt update
Observe the repo is under mongodb-org
—avoid confusion with mongodb
from universe.
3. Install the MongoDB Server (6.0+)
sudo apt install -y mongodb-org
This pulls in mongod
, mongos
, and command-line tools aligned to 6.0.x (verify with):
mongod --version
Example output:
db version v6.0.11
git version: 7c6217c618085b0c23a16de7e7eecc123aa4374b
allocator: tcmalloc
Note: If you see a major.minor version mismatch, your APT sources may be stale or misconfigured.
4. Systemd Integration and ulimit Hardening
MongoDB packaging for Ubuntu installs a systemd service—no need to manually daemonize.
sudo systemctl enable mongod
sudo systemctl start mongod
sudo systemctl status mongod
Critically, Linux defaults for nofile
and nproc
are insufficient on a busy system. Override by creating /etc/security/limits.d/mongodb.conf
:
mongodb soft nproc 64000
mongodb hard nproc 64000
mongodb soft nofile 64000
mongodb hard nofile 64000
These numbers match field experience for 10k+ collections and moderate sharding. Adjust if you expect unusually high concurrency.
Known issue: These limits require user re-login. For services: always restart after changing limits.
5. Basic Secure Configuration: /etc/mongod.conf
Bind Address
By default, MongoDB binds to 127.0.0.1
. For single-node, local deployments, that's enough. Clustered or containerized setups will need refinement:
net:
port: 27017
bindIp: 127.0.0.1,10.0.1.4 # Example: allow app server via private subnet
Never use 0.0.0.0
in production unless fully isolated by external firewalls.
Authentication
Insecure by default—must be fixed:
security:
authorization: enabled
Save and restart:
sudo systemctl restart mongod
Gotcha: If you enable authentication before creating users, you may lock yourself out. Order matters.
6. Creating an Admin User (Initial RBAC Bootstrap)
Without at least one admin user, RBAC makes the server inaccessible. Temporarily connect before enforcing net restrictions if needed.
mongosh --port 27017
Within the prompt:
use admin
db.createUser({
user: "admin",
pwd: "<yourStrongPassword>",
roles: [
{ role: "userAdminAnyDatabase", db: "admin" },
"readWriteAnyDatabase"
]
})
Exit. Now all future connections will require authentication.
7. Confirm RBAC Works
Unauthenticated connection should now fail:
mongosh --port 27017 --eval 'db.runCommand({ connectionStatus: 1 })'
Expected error:
MongoServerError: Authentication failed.
Now try with auth:
mongosh -u admin -p '<yourStrongPassword>' --authenticationDatabase admin --port 27017
If login succeeds and db.runCommand({connectionStatus: 1})
returns roles, authentication is properly enforced.
8. TLS Encryption (Optional but Strongly Recommended)
Insecure, plaintext traffic is exposed on internal networks. For production, enable TLS endpoint encryption:
Generate a PEM certificate (example with Let's Encrypt or internal CA), then update:
net:
tls:
mode: requireTLS
certificateKeyFile: /etc/ssl/mongodb.pem
CAFile: /etc/ssl/ca.pem
Restart mongod
for changes.
Trade-off: Enabling TLS increases CPU usage ~5–15%. Always benchmark your bottleneck.
9. Operational Hardening (Monitoring and Backup)
- Backups: Regular
mongodump
scheduled viacron
, or opt for LVM snapshots if the dataset is large. - Monitoring: Export Prometheus metrics via mongodb_exporter or Datadog agent.
- Disaster testing: Periodically perform restore and failover drills.
Pre-Production Checklist
Checkpoint | Status |
---|---|
Official MongoDB ≥6.0.x installed | ✅ |
Systemd service & ulimits hardened | ✅ |
Bind IP restricted to known networks | ✅ |
RBAC enabled, admin user created | ✅ |
RBAC & connection verified by test | ✅ |
TLS encrypted traffic (if required) | ☐ (optional) |
Operational monitoring in place | ☐ |
Automated backups configured | ☐ |
Final Notes
A hardened MongoDB deployment on Ubuntu 22.04 demands deliberate configuration—never settle for default installs in production. Security and reliability are set at provisioning, not after the fact. Plan upgrades for minor releases (apt upgrade
will track 6.0.x within the official repo).
Alternate approach: If managing OS and upgrades is not practical, consider using MongoDB Atlas or a managed instance—sacrificing some flexibility for operational simplicity.
There is always an edge-case. Network partition? ReplSet elections gone wrong? With the above setup, at least your database starts from a defensible baseline.
If you encounter silent failures, consult /var/log/mongodb/mongod.log
—default log path, unless rotated or redirected in mongod.conf
.
No install guide is perfect—compliance and integration specifics differ. Here's a foundation. Iterate as your use case grows.