MongoDB 8.0 Community on Ubuntu 22.04 on Azure User Guide
Overview
This image runs MongoDB 8.0 Community as a single node document database on Ubuntu 22.04 LTS. MongoDB is the dominant general purpose document database — JSON shaped records, a rich query language, secondary indexes, an aggregation framework, and a native driver surface that covers every mainstream application language. Version 8.0 is the latest major release and brings a rewritten query execution engine that lands roughly thirty percent improvements on complex aggregation pipelines, expanded queryable encryption capabilities, better time series collection performance, and improved shard key distribution heuristics for teams that later scale to sharded clusters.
This image ships the Server Side Public License version 1.0 Community edition of the mongodb-org package, installed from MongoDB Inc.'s official apt repository. The SSPL is important to understand. For internal application use inside your own infrastructure the Community edition is suitable and broadly used. The SSPL places obligations on anyone offering MongoDB itself as a service — if you are reselling a managed MongoDB product to third parties, confirm your licensing position with counsel or use MongoDB Atlas or a separately licensed edition. The image itself carries no restriction on operating your own applications on top of MongoDB.
Authentication is enforced out of the box. On the very first boot of every deployed virtual machine, two SCRAM-SHA-256 users are generated and written to a single file readable only by root: a marketplaceAdmin superuser with the cluster wide root role on the admin database, and a marketplace application user with readWrite and dbAdmin on a dedicated appdb database. Two virtual machines launched from the same gallery image never share credentials. The security.authorization directive is set to enabled in /etc/mongod.conf before mongod is ever started, so unauthenticated remote operations are rejected from the first packet.
The mongod listener binds on port 27017, the standard MongoDB wire protocol port. Driver connections, mongosh, mongodump, mongorestore, Compass, and every native driver work against it unchanged. MongoDB 8.0 does not add any new listener ports in a single node deployment. There is no embedded web admin UI — use MongoDB Compass, Studio 3T, or any other MongoDB client as a visual frontend.
The image is intended for teams that want a production posture single node MongoDB server on day one, with authentication enforced, credentials rotated per VM, and no hand rolled systemd plumbing. It is not a replica set (Section 7 explains how to extend into one), it is not TLS encrypted out of the box (Section 8 covers that), and it does not ship with sharding enabled. The SSPL 1.0 text is available at https://www.mongodb.com/licensing/server-side-public-license.
The brand is lowercase cloudimg throughout this guide. All cloudimg URLs in this guide use the form https://www.cloudimg.co.uk.
Prerequisites
Before you deploy this image you need:
- A Microsoft Azure subscription where you can create resource groups, virtual networks, and virtual machines
- Azure role permissions equivalent to Contributor on the target resource group
- An SSH public key for first login to the admin user account
- A virtual network and subnet in the same region as the Azure Compute Gallery the image is published into, with an associated network security group
- The Azure CLI (
azversion 2.50 or later) installed locally if you intend to use the CLI deployment path in Section 2 - The cloudimg MongoDB 8.0 offer enabled on your tenant in Azure Marketplace
Step 1: Deploy the Virtual Machine from the Azure Portal
Navigate to Marketplace in the Azure Portal, search for MongoDB 8.0, and select the cloudimg publisher entry. Click Create to begin the wizard.
On the Basics tab choose your subscription, target resource group, and region. The region must match the region your Azure Compute Gallery exposes the image in. Set the virtual machine name. Choose SSH public key as the authentication type, set the username to a name of your choice, and paste your SSH public key. Standard_D4s_v3 is the recommended starting size. MongoDB benefits substantially from memory for the WiredTiger cache, which the storage engine sizes by default at fifty percent of RAM above one gigabyte, so a sixteen gigabyte D4s_v3 profile leaves roughly seven gigabytes for the cache with enough headroom for the rest of the process and OS. Scale up to Standard_D8s_v3 or Standard_E8s_v3 for write heavy workloads, large working sets, or collections whose hot indexes exceed the default cache sizing.
On the Disks tab the recommended OS disk type is Standard SSD. The MongoDB data directory lives at /var/lib/mongodb. If you expect to ingest more than a few gigabytes per day, or if you intend to keep more than forty gigabytes of documents plus indexes on disk, attach a separate Premium SSD data disk now and plan to relocate the data directory before you ingest production traffic. MongoDB's IO profile is random access heavy under normal write workloads, so premium tier disks have a tangible effect on tail latency.
On the Networking tab select your existing virtual network and subnet. Attach a network security group that allows inbound TCP 22 from your management IP range and inbound TCP 27017 only from the virtual network CIDR or the specific application server subnets that need to talk to the database. Do not expose 27017 to the public internet. SCRAM-SHA-256 is strong authentication but an exposed database is an indefinite compromise target and there is no operational reason to open the listener publicly — driver traffic flows privately from your application tier.
On the Management, Monitoring, and Advanced tabs the defaults are appropriate. Click Review + create, wait for validation to pass, then click Create. Deployment takes around two minutes.
Step 2: Deploy the Virtual Machine from the Azure CLI
If you prefer the command line, use the gallery image resource identifier as the source. The exact resource identifier is published on your Partner Center plan. A representative invocation:
RG="mongodb-prod"
LOCATION="eastus"
VM_NAME="mongodb-01"
ADMIN_USER="dbadmin"
GALLERY_IMAGE_ID="/subscriptions/<sub-id>/resourceGroups/azure-cloudimg/providers/Microsoft.Compute/galleries/cloudimgGallery/images/mongodb-8-0-ubuntu-22-04/versions/<version>"
SSH_KEY="$(cat ~/.ssh/id_rsa.pub)"
az group create --name "$RG" --location "$LOCATION"
az network vnet create \
--resource-group "$RG" \
--name mongodb-vnet \
--address-prefix 10.60.0.0/16 \
--subnet-name mongodb-subnet \
--subnet-prefix 10.60.1.0/24
az network nsg create --resource-group "$RG" --name mongodb-nsg
az network nsg rule create \
--resource-group "$RG" --nsg-name mongodb-nsg \
--name allow-ssh-mgmt --priority 100 \
--source-address-prefixes "<your-mgmt-cidr>" \
--destination-port-ranges 22 --access Allow --protocol Tcp
az network nsg rule create \
--resource-group "$RG" --nsg-name mongodb-nsg \
--name allow-mongodb-vnet --priority 110 \
--source-address-prefixes 10.60.0.0/16 \
--destination-port-ranges 27017 --access Allow --protocol Tcp
az vm create \
--resource-group "$RG" \
--name "$VM_NAME" \
--image "$GALLERY_IMAGE_ID" \
--size Standard_D4s_v3 \
--storage-sku StandardSSD_LRS \
--admin-username "$ADMIN_USER" \
--ssh-key-values "$SSH_KEY" \
--vnet-name mongodb-vnet --subnet mongodb-subnet \
--nsg mongodb-nsg \
--public-ip-address "" \
--os-disk-size-gb 32
The --public-ip-address "" flag keeps the server off the public internet. Use a bastion host or your existing private connectivity to reach it.
Step 3: Connect via SSH
After deployment, find the private IP of the new virtual machine. From a host inside the same virtual network:
ssh dbadmin@<vm-ip>
The first login may take a few seconds while cloud init finalises. Once you have a shell, mongod has already been started by systemd and the first boot oneshot has already generated the per virtual machine SCRAM credentials.
Step 4: Retrieve the MongoDB Credentials
Two users are written by the mongod-firstboot.service systemd oneshot the very first time the virtual machine boots. The credentials live in a single file, readable only by root:
sudo cat /stage/scripts/mongodb-credentials.log
The file contains, at a minimum, these fields:
root.user=marketplaceAdmin
root.password=<generated>
root.authSource=admin
app.user=marketplace
app.password=<generated>
app.database=appdb
app.authSource=appdb
host=<private-ip>
port=27017
mechanism=SCRAM-SHA-256
For scripted use, extract a specific field with awk:
sudo awk -F= '/^root\.password=/ {print $2}' /stage/scripts/mongodb-credentials.log
Copy both passwords somewhere safe. The credentials file is not backed up anywhere else. If you lose it, Section 9 covers password rotation via the running server, but if the file is gone and neither user can authenticate the fastest recovery is to redeploy from the same image and migrate data.
Step 5: Connect with mongosh and Verify the Server
mongosh is already installed on the image. Confirm the server is live and authenticated:
sudo systemctl status mongod.service --no-pager | head -20
Confirm it is listening on 27017:
ss -ltn | grep ':27017 '
Confirm the shipped version is MongoDB 8.0:
mongod --version | head -2
Connect with mongosh as the admin user and list databases. The one liner below pulls the password from the credentials file at runtime, so nothing is echoed to your shell history:
ROOT_PW=$(sudo awk -F= '/^root\.password=/ {print $2}' /stage/scripts/mongodb-credentials.log)
mongosh --quiet --host 127.0.0.1 --port 27017 \
-u marketplaceAdmin -p "$ROOT_PW" --authenticationDatabase admin \
--eval 'db.adminCommand({listDatabases:1}).databases.forEach(d => print(d.name))'
A minimal deployment prints admin, config, and local. Confirm authentication is being enforced — an unauthenticated connection must fail:
mongosh --quiet --host 127.0.0.1 --port 27017 \
--eval 'db.adminCommand({listDatabases:1}).databases.length' 2>&1 | grep -E "Unauthorized|requires authentication" | head -1
A line containing requires authentication (or Unauthorized) confirms security.authorization: enabled is in effect in /etc/mongod.conf.
Step 6: Create a Database and Collection, Insert and Find Documents
A minimum working end to end exercise authenticating as the application user:
APP_PW=$(sudo awk -F= '/^app\.password=/ {print $2}' /stage/scripts/mongodb-credentials.log)
mongosh --quiet --host 127.0.0.1 --port 27017 \
-u marketplace -p "$APP_PW" --authenticationDatabase appdb appdb <<'EOS'
db.devices.insertMany([
{ serial: "A001", model: "sensor-pro", firmware: "1.4.0", registeredAt: new Date() },
{ serial: "A002", model: "sensor-pro", firmware: "1.4.1", registeredAt: new Date() },
{ serial: "A003", model: "sensor-lite", firmware: "1.1.0", registeredAt: new Date() }
]);
print("inserted:", db.devices.countDocuments({}));
print("--- firmware 1.4.x ---");
db.devices.find({ firmware: { $regex: /^1\.4\./ } }).forEach(d => printjson(d));
EOS
MongoDB creates the database and the collection on first write. Re running the block on a clean collection is the fastest sanity test after any server change.
Step 7: Create Indexes for Query Performance
Without indexes, any predicate on a collection scans every document. Every production collection should have indexes supporting its hot query shapes. For the devices collection above:
APP_PW=$(sudo awk -F= '/^app\.password=/ {print $2}' /stage/scripts/mongodb-credentials.log)
mongosh --quiet --host 127.0.0.1 --port 27017 \
-u marketplace -p "$APP_PW" --authenticationDatabase appdb appdb <<'EOS'
db.devices.createIndex({ serial: 1 }, { unique: true });
db.devices.createIndex({ model: 1, firmware: 1 });
print("--- indexes ---");
db.devices.getIndexes().forEach(i => printjson(i));
print("--- explain for model+firmware filter ---");
var plan = db.devices.find({ model: "sensor-pro", firmware: "1.4.1" }).explain("queryPlanner");
print("winning stage:", plan.queryPlanner.winningPlan.inputStage ? plan.queryPlanner.winningPlan.inputStage.stage : plan.queryPlanner.winningPlan.stage);
EOS
winningPlan.inputStage.stage of IXSCAN confirms the new compound index is being used rather than a full COLLSCAN. Unique indexes enforce uniqueness on write, so any subsequent insert with a duplicate serial is rejected by the server — a common use for the natural key of a tenant or device registry.
Step 8: Back Up and Restore with mongodump
mongodump and mongorestore ship with the image as part of the mongodb-database-tools package. They produce a BSON archive that is portable across MongoDB versions within the 7.x to 8.x band and is the recommended backup mechanism for single node deployments. For larger clusters, consider MongoDB Ops Manager or Cloud Manager for incremental block level snapshots. A full dump of the appdb database authenticated as the admin user:
ROOT_PW=$(sudo awk -F= '/^root\.password=/ {print $2}' /stage/scripts/mongodb-credentials.log)
sudo mkdir -p /var/backups/mongodb
sudo chown $(id -u):$(id -g) /var/backups/mongodb
mongodump --host 127.0.0.1 --port 27017 \
-u marketplaceAdmin -p "$ROOT_PW" --authenticationDatabase admin \
--db appdb --out /var/backups/mongodb/$(date -u +%Y%m%dT%H%M%S)
ls -la /var/backups/mongodb/
You will see a directory named with today's UTC timestamp containing appdb/ with BSON and metadata files per collection. Restoration reverses the flow — see https://www.mongodb.com/docs/database-tools/mongorestore/ for the full flag reference including --drop for destructive restores and --nsInclude for selective restores. In production, schedule mongodump under cron or a systemd timer, push the archive directory to Azure Blob Storage or another durable location, and retain according to your recovery point objective.
Step 9: Plan a Replica Set for High Availability
A single node MongoDB server has no automatic failover. For high availability in production, run a replica set of at least three mongod members spread across availability zones. Replica sets elect a primary and replicate writes to secondaries; if the primary fails, a secondary is promoted automatically and drivers transparently reconnect.
The cloudimg image ships configured for standalone operation — replication.replSetName is not set in /etc/mongod.conf. To extend to a replica set you deploy two additional virtual machines from the same gallery image, set a shared replication.replSetName in /etc/mongod.conf on all three, configure net.bindIp to include the internal hostnames, restart each mongod, and run rs.initiate() once from the mongosh on the intended primary. The full procedure including keyfile based inter node authentication is documented at https://www.mongodb.com/docs/manual/tutorial/deploy-replica-set/. Plan node placement before provisioning — inter node latency drives replication lag and election time, so same region, different availability zone is the right posture for most deployments.
Replica sets are also the prerequisite for MongoDB's change streams feature, which is the supported way to build event driven integrations on top of a collection. If you expect to publish MongoDB writes to a downstream system like Kafka or an internal event bus, plan the replica set before the integration is wired, not after.
Step 10: Enable TLS for the Wire Protocol
MongoDB 8.0 supports TLS termination natively at the mongod listener. On a new deployment, obtain or mint a server certificate (for production, use a certificate from your internal certificate authority or an ACME issued cert with a SAN for the private DNS name), concatenate the certificate and key into a PEM bundle that mongod can read, and update /etc/mongod.conf to the following block:
net:
port: 27017
bindIp: 0.0.0.0
tls:
mode: requireTLS
certificateKeyFile: /etc/ssl/mongodb.pem
CAFile: /etc/ssl/internal-ca.pem
requireTLS rejects any plain wire protocol connection — drivers must connect with tls=true. Restart the service (sudo systemctl restart mongod) and verify connections now require TLS with mongosh --tls --tlsCAFile /etc/ssl/internal-ca.pem --host <private-dns-name>. For a deeper treatment of MongoDB TLS options including preferTLS (soft migration mode), client certificate authentication, and cipher suite restrictions, see https://www.mongodb.com/docs/manual/tutorial/configure-ssl/.
Step 11: Security Hardening Before Production
Before you put real workload through the server, tighten the posture along the following axes.
Rotate the generated passwords. The bootstrap passwords are strong random SCRAM credentials, but your organisation's policy may require scheduled rotation. Rotate marketplaceAdmin as its own admin user by connecting with mongosh and running:
ROOT_PW=$(sudo awk -F= '/^root\.password=/ {print $2}' /stage/scripts/mongodb-credentials.log)
NEW_ROOT_PW=$(openssl rand -base64 48 | tr -d '=+/' | cut -c1-32)
mongosh --quiet --host 127.0.0.1 --port 27017 \
-u marketplaceAdmin -p "$ROOT_PW" --authenticationDatabase admin \
admin --eval "db.changeUserPassword('marketplaceAdmin', '$NEW_ROOT_PW')"
echo "new root password: $NEW_ROOT_PW"
sudo sed -i "s|^root\.password=.*|root.password=$NEW_ROOT_PW|" /stage/scripts/mongodb-credentials.log
Re authenticate with the new password to confirm the change took effect, then destroy the shell history or clear the NEW_ROOT_PW variable. Rotate the application user the same way, updating app.password= in the credentials file and redeploying any applications that cached the old value.
Restrict 27017 at the network edge. The network security group rule in Section 2 limited inbound 27017 to the virtual network CIDR. Tighten further to specific application subnet CIDRs or to an Azure Private Link endpoint so the listener is not reachable from unrelated subnets on the same VNet. The database should be a deliberate backend hop, never a default one.
Enable field level encryption for sensitive data. MongoDB 8.0's client side field level encryption (CSFLE) and queryable encryption allow sensitive fields — payment details, identity numbers, health records — to be encrypted before they ever leave the driver, with the encryption keys held in a separate key vault collection or in an external KMS such as Azure Key Vault. Server side operations on encrypted fields are limited to equality (CSFLE) or equality plus range (queryable encryption version 8.0). The full configuration requires a key management service, a local master key or KMS integration, and driver side schema declarations; see https://www.mongodb.com/docs/manual/core/queryable-encryption/ for the MongoDB 8.0 feature matrix and https://www.mongodb.com/docs/manual/core/csfle/ for the mature CSFLE path.
Limit the admin user's scope. The marketplaceAdmin user is the root role on the admin database, which is the full cluster privilege set. For day to day application operations, use the marketplace application user — which only holds readWrite and dbAdmin on appdb. Create additional application users scoped to their own databases as the application footprint grows, and reserve the marketplaceAdmin credential for administrative work.
Turn on audit logging. MongoDB 8.0 Community does not include the Enterprise audit subsystem, but the standard mongod log (at /var/log/mongodb/mongod.log) records authentication attempts, schema changes, and slow operations. Ship the log to Azure Monitor or your existing SIEM via the azure monitor agent so failed login attempts and privileged operations are visible outside the VM.
Plan for upgrades. MongoDB 8.0 will receive patch level updates (8.0.1, 8.0.2, and so on) via the mongodb-org apt repository already configured on the image. Run sudo apt-get update && sudo apt-get upgrade mongodb-org monthly and restart the service in a maintenance window. Major version upgrades (8.0 to 9.0) require following the MongoDB upgrade procedure including compatibility setting changes documented at https://www.mongodb.com/docs/manual/release-notes/.
Detach the placeholder application user if unused. If your workload does not use the seeded marketplace user — for example if you create per tenant or per service users programmatically — drop it to reduce attack surface:
ROOT_PW=$(sudo awk -F= '/^root\.password=/ {print $2}' /stage/scripts/mongodb-credentials.log)
mongosh --quiet --host 127.0.0.1 --port 27017 \
-u marketplaceAdmin -p "$ROOT_PW" --authenticationDatabase admin \
appdb --eval 'db.dropUser("marketplace")'
Then remove the app.* lines from the credentials file to match the running server.
Step 12: Where to Go Next
Driver integration. Every mainstream language has a native MongoDB driver supporting the 8.0 wire protocol. Representative examples: Node.js (mongodb on npm), Python (pymongo), Go (go.mongodb.org/mongo-driver), Java (mongodb-driver-sync), C# (MongoDB.Driver), Rust (mongodb on crates.io). Each reads a standard mongodb://user:pw@host:27017/db?authSource=db connection string and supports TLS, replica set connection strings, and retryable writes.
Observability. MongoDB emits Prometheus compatible metrics via the community mongodb_exporter. Scrape it from your existing Prometheus stack or from Azure Monitor managed Prometheus, and alert on replication lag (once Section 9 is in place), connection count, oplog window, slow query count, and disk use.
MongoDB Compass. The official GUI client. Install it on a jump host or your workstation and connect via the same mongodb:// URI. Compass is particularly valuable for ad hoc aggregation pipeline authoring and for visualising schemas inferred from a sample of documents.
Extended reading. The official MongoDB 8.0 release notes at https://www.mongodb.com/docs/manual/release-notes/8.0/ cover every query engine change, every new server parameter, and every removed feature. Read the upgrade notes section before rolling any MongoDB 8.0 code into production that previously ran against 7.0 or earlier.
This guide covers the first mile of a MongoDB 8.0 deployment on Azure using the cloudimg image. For ongoing operations, refer to the official MongoDB manual at https://www.mongodb.com/docs/manual/ and to the cloudimg support portal for image specific questions.