FerretDB on Ubuntu 24.04 on Azure User Guide
Overview
FerretDB is the open-source MongoDB alternative. It speaks the MongoDB wire protocol, so any MongoDB driver or mongosh connects to it unchanged, but it stores your data in PostgreSQL via the DocumentDB extension. You get MongoDB-compatible document operations on a fully open-source, Apache-2.0 stack with PostgreSQL's durability and tooling underneath. The cloudimg image installs FerretDB 2.7.0 on top of PostgreSQL 17 with the official DocumentDB extension, runs each as a dedicated system user, stores the PostgreSQL data directory on a dedicated Azure data disk, and rotates a unique MongoDB password into the image on first boot. Backed by 24/7 cloudimg support.
What is included:
- FerretDB 2.7.0 (
ferretdb) - the MongoDB-compatible database, Apache-2.0 licensed - PostgreSQL 17 with the official DocumentDB extension 0.107.0 as the storage backend
- A unique per-VM MongoDB password generated on first boot (no shared default credential)
- The PostgreSQL data directory on a dedicated 30 GiB Azure data disk at
/var/lib/ferretdb - Loopback-only MongoDB wire-protocol listener on
27017with SCRAM-SHA-256 authentication - A debug/health HTTP listener on
127.0.0.1:8088(/debug/livez,/debug/readyz) - 24/7 cloudimg support
This is a database product: FerretDB listens on 127.0.0.1:27017 only by default. The MongoDB wire-protocol port is not opened to the internet until you open it in your NSG - connect locally on the VM, over an SSH tunnel, or open 27017 deliberately (see Step 8).
Prerequisites
An active Azure subscription, an SSH key pair, and a VNet + subnet in the target region. Standard_B2s (2 vCPU / 4 GiB RAM) is a good starting point. NSG inbound: allow 22/tcp from your management network. Open 27017/tcp only when you intend to reach FerretDB remotely (Step 8).
Step 1 - Deploy from the Azure Marketplace
Sign in to the Azure Portal, choose Create a resource, search the Marketplace for FerretDB by cloudimg, and select Create. On Basics pick your subscription, resource group, region and size; under Administrator account choose SSH public key and paste your key; under Inbound port rules allow SSH (22) only. Then Review + create -> Create.
Step 2 - Deploy from the Azure CLI
az vm create \
--resource-group <your-rg> \
--name ferretdb \
--image <marketplace-image-urn> \
--size Standard_B2s \
--admin-username azureuser \
--ssh-key-values ~/.ssh/id_ed25519.pub \
--vnet-name <your-vnet> --subnet <your-subnet> \
--public-ip-sku Standard
Step 3 - Connect to your VM
ssh azureuser@<vm-public-ip>
Step 4 - Confirm FerretDB is installed and running
FerretDB runs alongside its PostgreSQL backend. Confirm the version and that both services are active, then check the listeners:
ferretdb --version
systemctl is-active postgresql.service ferretdb.service
sudo ss -tln | grep -E ':27017|:8088|:5432'
You should see FerretDB v2.7.0, both services active, and the loopback-only listeners:
version: v2.7.0
active
active
LISTEN 0 4096 127.0.0.1:5432 0.0.0.0:*
LISTEN 0 4096 127.0.0.1:8088 0.0.0.0:*
LISTEN 0 4096 127.0.0.1:27017 0.0.0.0:*

Step 5 - Retrieve your per-VM MongoDB password
Each VM generates its own unique MongoDB password on first boot and writes it to a root-only credentials file. The MongoDB username is admin:
sudo cat /root/ferretdb-credentials.txt
The file contains FERRETDB_USERNAME, FERRETDB_PASSWORD, the connection string and the access instructions. Store the password in your secrets manager. In the commands below, <FERRETDB_PASSWORD> stands for the value of FERRETDB_PASSWORD.
Step 6 - Connect and authenticate with mongosh
FerretDB requires authentication (SCRAM-SHA-256, delegated to PostgreSQL). Connect with mongosh using the per-VM admin credentials and run a ping:
mongosh "mongodb://admin:<FERRETDB_PASSWORD>@127.0.0.1:27017/?authMechanism=SCRAM-SHA-256" \
--quiet --eval 'db.runCommand({ping:1})'
connected to FerretDB v2.7.0
{ ok: 1 }
A wrong password is rejected with an authentication error, so the database is never open without the credential. Any MongoDB driver (Node, Python pymongo, Go, Java, etc.) connects with the same mongodb://admin:<password>@host:27017/ URI.

Step 7 - Store and query documents
FerretDB speaks the MongoDB wire protocol, so MongoDB CRUD works unchanged. Insert documents, read one back, and run a query:
mongosh "mongodb://admin:<FERRETDB_PASSWORD>@127.0.0.1:27017/catalog?authMechanism=SCRAM-SHA-256" --quiet --eval '
db.products.deleteMany({});
db.products.insertMany([
{_id:1, name:"widget", price:9.99, tags:["a","b"]},
{_id:2, name:"gadget", price:19.5, tags:["c"]}
]);
print("inserted: " + db.products.countDocuments({}));
printjson(db.products.findOne({_id:1}));
db.products.find({price:{$gt:10}}).forEach(d => print(d.name + " = " + d.price));
'
inserted: 2
{ _id: 1, name: 'widget', price: 9.99, tags: [ 'a', 'b' ] }
gadget = 19.5

Step 8 - Open the MongoDB wire-protocol port for remote access
By default FerretDB binds to 127.0.0.1:27017 only and the port is not exposed - this is the secure default. To reach it from your workstation or application you have two options.
Option A - SSH tunnel (no NSG change, good for admin access):
# On your workstation:
ssh -L 27017:127.0.0.1:27017 azureuser@<vm-public-ip>
# In another terminal, with a local mongosh:
mongosh "mongodb://admin:<FERRETDB_PASSWORD>@127.0.0.1:27017/?authMechanism=SCRAM-SHA-256"
Option B - bind publicly and open the NSG port (for applications):
# 1. On the VM, set the listen address to all interfaces and restart:
sudo sed -i 's|^FERRETDB_LISTEN_ADDR=.*|FERRETDB_LISTEN_ADDR=0.0.0.0:27017|' /etc/ferretdb/ferretdb.env
sudo systemctl restart ferretdb
# 2. Open 27017/tcp in your Azure NSG (restrict the source to your app subnet):
az network nsg rule create --resource-group <your-rg> --nsg-name <your-nsg> \
--name allow-mongodb --priority 1010 --access Allow --protocol Tcp \
--destination-port-ranges 27017 --source-address-prefixes <your-app-cidr>
Then connect from your application with the public connection string:
mongodb://admin:<FERRETDB_PASSWORD>@<vm-public-ip>:27017/
Authentication is always enforced. Never expose 27017 to the internet without restricting the NSG source and using TLS termination in front of FerretDB.
Step 9 - Confirm health and the document store
FerretDB exposes a debug/health listener on 127.0.0.1:8088. /debug/livez is a liveness probe and /debug/readyz is a readiness probe that confirms the PostgreSQL + DocumentDB backend is serving. Check both, then list databases and collections:
curl -fsS -o /dev/null -w 'livez: HTTP %{http_code}\n' http://127.0.0.1:8088/debug/livez
curl -fsS -o /dev/null -w 'readyz: HTTP %{http_code}\n' http://127.0.0.1:8088/debug/readyz
mongosh "mongodb://admin:<FERRETDB_PASSWORD>@127.0.0.1:27017/catalog?authMechanism=SCRAM-SHA-256" \
--quiet --eval 'db.adminCommand({listDatabases:1}).databases.forEach(d => print(d.name)); print("---"); db.getCollectionNames().forEach(c => print(c))'
livez: HTTP 200
readyz: HTTP 200
catalog
postgres
---
products

Maintenance
- Persistence: the PostgreSQL data directory (the document store) lives on the dedicated data disk at
/var/lib/ferretdb, so your data survives reboots and the volume is independently resizable. - Password: the MongoDB user
adminis a PostgreSQL role; rotate its password withsudo -u postgres psql -c "ALTER ROLE admin WITH PASSWORD '<new>';"then updateFERRETDB_POSTGRESQL_URLin/etc/ferretdb/ferretdb.envandsudo systemctl restart ferretdb. - Adding users: create more MongoDB users as PostgreSQL roles -
sudo -u postgres psql -c "CREATE ROLE app WITH LOGIN PASSWORD '...';"- or withdb.createUser({user:'app', pwd:'...', roles:[]})in mongosh. - Tuning: edit
/var/lib/ferretdb/pg17/postgresql.conf(for exampleshared_buffers,work_mem) andsudo systemctl restart postgresql. - Security patches: unattended-upgrades remains enabled so the OS continues to receive security updates automatically.
- Compatibility: FerretDB targets the MongoDB wire protocol - existing MongoDB drivers, libraries and tooling work against
27017.
Support
cloudimg provides 24/7 expert support for this image. Contact support@cloudimg.co.uk.
FerretDB is a trademark of FerretDB Inc. MongoDB is a trademark of MongoDB, Inc. PostgreSQL is a trademark of the PostgreSQL Community Association. This image is provided by cloudimg and is not affiliated with or endorsed by FerretDB Inc., MongoDB, Inc. or the PostgreSQL Community Association.