FerretDB
Overview
FerretDB is an open source database that speaks the MongoDB wire protocol. Applications, MongoDB drivers, mongosh and tools such as MongoDB Compass connect to it as they would to MongoDB. FerretDB stores the documents in PostgreSQL through the DocumentDB extension.
This image runs FerretDB 2.7.0 on PostgreSQL 17 with DocumentDB 0.107.0, the release that FerretDB 2.7.0 is built for, on one VM. The SecureAnyCloud image adds a password that is unique to your VM, TLS, hardened services and a dedicated data disk.
What you get:
- No default login, a password unique to your VM. The image ships no PostgreSQL cluster and no database. First boot creates your VM's own cluster on the data disk, installs DocumentDB and creates the MongoDB administrator admin with a 32-character password generated on the VM. Only a SCRAM-SHA-256 verifier of that password is handed to PostgreSQL. The password itself never reaches PostgreSQL, a command line, a log or the journal. It is written to the root-only file
/root/ferretdb-credentials.txt. FerretDB and PostgreSQL refuse to start until first boot has finished. - No trust rule, no PostgreSQL password. PostgreSQL listens on
127.0.0.1:5432only, and every connection there must prove a password with SCRAM-SHA-256. On the local socket, a PostgreSQL role signs in only as the matching operating system user (peer authentication). FerretDB, DocumentDB's background jobs and you (as the operating system'spostgresuser) use the socket. PostgreSQL's ownpostgresandferretdbroles have no password, so there is no PostgreSQL credential to steal. There is notrustrule anywhere inpg_hba.conf. - FerretDB on localhost, with TLS. FerretDB listens on
127.0.0.1:27017and, with a certificate generated on your VM's first boot, on127.0.0.1:27018over TLS. Nothing but SSH is reachable from the network until you choose to open the TLS port to your virtual network (Step 9). - A FerretDB built for this image. The FerretDB 2.7.0 release binary was built with Go 1.25.4 and modules that now carry fixed security advisories. SecureAnyCloud therefore compiles FerretDB 2.7.0 from its release source with Go 1.27.3 and the fixed module releases, and govulncheck reports no vulnerabilities in it. The build is reproducible, and its provenance is on the VM (/usr/share/doc/ferretdb/BUILD-PROVENANCE.txt).
- Hardened services. FerretDB runs as an unprivileged
ferretdbuser with no capabilities, a read-only view of the system and no access to/root. FerretDB, PostgreSQL and the first boot service are blocked from the Azure Instance Metadata Service and the platform wire server. FerretDB's telemetry is off, andmongoshsends no telemetry for any user and keeps no session logs. Only the open sourcemongoshshell is installed, not MongoDB's proprietary encryption library. pg_cron does not record DocumentDB's once-a-second background jobs, so its history table and the PostgreSQL log cannot grow without bound. - Your data on its own disk. The PostgreSQL data directory (
/var/lib/ferretdb/pg17) is on a dedicated 30 GiB Azure managed data disk that you can grow or snapshot on its own. - Fully patched Ubuntu 24.04 LTS at build time, with unattended security upgrades switched on.
What is on the image: FerretDB 2.7.0 (/usr/local/bin/ferretdb), PostgreSQL 17 with pg_cron, PostGIS, RUM and pgvector from the PostgreSQL Global Development Group (PGDG) repository, the DocumentDB extension 0.107.0 for FerretDB 2.7.0, mongosh 2.13.0 (the MongoDB Shell), Ubuntu 24.04 LTS, cloud-init and the Azure Linux agent. There is no MongoDB server on the image.
Admin user: azureuser (or the name you choose); Recommended size: Standard_B2s to start
Prerequisites
- An Azure subscription with permission to create virtual machines, and an SSH key pair (or a password) for the admin account.
- A Network Security Group that allows TCP 22 (SSH) from your admin network. FerretDB listens on the loopback address only, so no database port needs to be open. You reach FerretDB through an SSH tunnel (Step 8), or you open the TLS port to your application subnet later (Step 9). Never open 27017, 27018 or 5432 to the internet.
Deploy from the Azure Portal
- Find FerretDB on Ubuntu 24.04 LTS by SecureAnyCloud in the Azure Marketplace and choose Create.
- On the Basics tab, choose a resource group, region and size.
Standard_B2s(2 vCPU, 4 GiB RAM) is a sensible starting point. Size up for larger working sets. - Under Administrator account, use the username
azureuserwith an SSH public key (recommended) or a password. The image honours whichever you choose. - Under Inbound port rules, allow SSH (22) only. After the VM is created, restrict it to your own address range in the Network Security Group.
- On the Disks tab, check the image's 30 GiB data disk for
/var/lib/ferretdb. Make it as large as your data needs. - Choose Review + create, then Create. First boot takes well under a minute after the VM is running.
Deploy with the Azure CLI
Accept the Marketplace terms once per subscription, then create the VM:
# Accept the Marketplace terms once per subscription (required before the first CLI deploy)
az vm image terms accept --urn sac1647283583153:ferretdb-ubuntu-24-04:default:latest
az vm create \
--resource-group <your-resource-group> \
--name ferretdb \
--image sac1647283583153:ferretdb-ubuntu-24-04:default:latest \
--size Standard_B2s \
--admin-username azureuser \
--ssh-key-values ~/.ssh/id_rsa.pub \
--public-ip-sku Standard \
--nsg-rule SSH--nsg-rule SSH creates a Network Security Group that allows SSH only, which is all FerretDB needs. Do not run az vm open-port for 27017, 27018 or 5432, because that opens the port to every address on the internet.
Connect to your VM
Connect over SSH as the admin user:
ssh azureuser@<vm-public-ip>Check the services
First boot records the VM's public address and creates the PostgreSQL cluster, the administrator and the certificate. Then PostgreSQL and FerretDB start. Check the units and the first boot marker:
systemctl is-active ferretdb-firstboot postgresql@17-main ferretdb
sudo test -f /var/lib/sac/data/ferretdb-firstboot.done && echo FIRSTBOOT_DONE ferretdb --version | head -1On the first boot, all three units are active and the first boot marker is present. On later boots ferretdb-firstboot shows inactive because it runs once:
active active active FIRSTBOOT_DONE version: v2.7.0Only SSH listens on a network address. FerretDB listens on the loopback address on port 27017 (MongoDB protocol), port 27018 (MongoDB protocol over TLS) and port 8088 (its health and metrics handler). PostgreSQL listens on 127.0.0.1:5432 and on its local socket. Confirm the listeners:
sudo ss -lntp | awk 'NR>1 {print $4, $6}' | sed -E 's/,pid=[0-9]+,fd=[0-9]+//g' | grep -v -E '^127\.0\.0\.5[34]' | sort0.0.0.0:22 users:(("sshd"),("systemd")) 127.0.0.1:27017 users:(("ferretdb")) 127.0.0.1:27018 users:(("ferretdb")) 127.0.0.1:5432 users:(("postgres")) 127.0.0.1:8088 users:(("ferretdb")) [::]:22 users:(("sshd"),("systemd"))The data is on the dedicated data disk, and FerretDB reports ready once PostgreSQL and DocumentDB answer. Check both:
findmnt -no FSTYPE,TARGET /var/lib/ferretdb
sudo du -sh /var/lib/ferretdb/pg17 curl -s -o /dev/null -w 'readyz HTTP %{http_code}\n' http://127.0.0.1:8088/debug/readyzext4 /var/lib/ferretdb 65M /var/lib/ferretdb/pg17 readyz HTTP 200Get your administrator password
sudo cat /root/ferretdb-credentials.txtOnly root can read the file:
# FerretDB 2.7.0 on Ubuntu 24.04 - generated on first boot by ferretdb-firstboot.service
# This password is unique to this VM; none was baked into the image. Keep this file secret. FERRETDB_USERNAME=admin FERRETDB_PASSWORD=<FERRETDB_PASSWORD> FERRETDB_HOST=127.0.0.1 FERRETDB_PORT=27017 FERRETDB_TLS_PORT=27018 FERRETDB_TLS_CA=/etc/ferretdb/tls/ferretdb.crt
# On the VM (mongosh signed in as admin; the password never goes on a command line):
sudo ferretdb-shell
# Connection string, on the VM or through an SSH tunnel to 127.0.0.1:27017 (replace <password>):
# mongodb://admin:<password>@127.0.0.1:27017/?authMechanism=SCRAM-SHA-256
# TLS listener (127.0.0.1:27018 by default; give clients /etc/ferretdb/tls/ferretdb.crt as the CA file):
# mongodb://admin:<password>@<host>:27018/?authMechanism=SCRAM-SHA-256&tls=true&tlsCAFile=ferretdb.crt
# FerretDB listens on the loopback interface only; ports 27017 and 27018 are not open to the network. To let clients
# in your virtual network connect, use the TLS listener (27018) and allow it in your NSG from their subnet only.
# User guide: https://secureanycloud.com/stacks/ferretdb/Store the password in your secrets manager. In the commands that follow, <FERRETDB_PASSWORD> stands for the value of FERRETDB_PASSWORD.
Use the MongoDB shell on the VM
sudo ferretdb-shell opens mongosh signed in as admin. It reads the password from the credentials file itself, so the password never appears on a command line or in your shell history. With no arguments it opens an interactive shell. With --eval it runs a command and exits:
sudo ferretdb-shell --eval 'db.runCommand({ping: 1})'{ ok: 1 }Write some documents, add an index and query them, as you would on MongoDB.
sudo ferretdb-shell --eval 'const inv = db.getSiblingDB("inventory"); inv.items.insertMany([{sku: "A-100", qty: 25}, {sku: "B-200", qty: 40}, {sku: "C-300", qty: 75}]); inv.items.createIndex({sku: 1}, {unique: true}); printjson(inv.items.find({qty: {$gt: 30}}, {_id: 0}).sort({qty: 1}).toArray())'[ { sku: 'B-200', qty: 40 }, { sku: 'C-300', qty: 75 } ]FerretDB identifies itself in buildInfo.
sudo ferretdb-shell --eval 'printjson(db.adminCommand({buildInfo: 1}).ferretdb)'{ version: 'v2.7.0', package: 'sac' }Remove the example database when you have finished with it:
sudo ferretdb-shell --eval 'db.getSiblingDB("inventory").dropDatabase()'{ ok: 1, dropped: 'inventory' }FerretDB covers the MongoDB features that most applications use: CRUD, indexes including text indexes, aggregation pipelines, cursors and user management. Before you migrate, check the FerretDB compatibility documentation for the commands and operators that your application relies on.
Create a user for your application
Give each application its own user, so that you can change or revoke its password without touching admin. Run this in sudo ferretdb-shell. passwordPrompt() asks for the new password, so it is never written on a command line:
use admin db.createUser({user: "appuser", pwd: passwordPrompt(), roles: [{role: "clusterAdmin", db: "admin"}, {role: "readWriteAnyDatabase", db: "admin"}]})FerretDB 2.7.0 stores every user as a PostgreSQL role and accepts two role sets: clusterAdmin with readWriteAnyDatabase, and readAnyDatabase. FerretDB does not yet enforce MongoDB roles: every user it authenticates can read and write every database. Use separate users to separate credentials, and keep network access to FerretDB as narrow as you can (Steps 8 and 9).
Change a user's password with db.getSiblingDB("admin").updateUser("appuser", {pwd: passwordPrompt()}). Remove a user with db.getSiblingDB("admin").dropUser("appuser").
Connect from your own computer through an SSH tunnel
FerretDB is not exposed to the network. From your computer, open an SSH tunnel, which encrypts the connection, and point mongosh, MongoDB Compass or your application at the local end of it:
ssh -N -L 27017:127.0.0.1:27017 azureuser@<vm-public-ip> mongosh "mongodb://admin@127.0.0.1:27017/?authMechanism=SCRAM-SHA-256" -p-p with no value makes mongosh prompt for the password. In MongoDB Compass, use the connection string mongodb://admin:<password>@127.0.0.1:27017/?authMechanism=SCRAM-SHA-256&directConnection=true.
Allow TLS connections from your virtual network
To let application servers in your virtual network connect directly, use FerretDB's TLS listener rather than the plain one. The certificate generated on first boot names localhost, 127.0.0.1 and the VM's host name and private and public addresses. Add your own DNS name if clients use one, open the TLS listener to the network, and restart FerretDB:
sudo ferretdb-tls-cert --renew db.example.internal
sudo sed -i 's/^FERRETDB_LISTEN_TLS=127.0.0.1:27018$/FERRETDB_LISTEN_TLS=0.0.0.0:27018/' /etc/ferretdb/ferretdb.env
sudo systemctl restart ferretdbThen allow TCP 27018 in the VM's Network Security Group from your application subnet only. Replace <your-app-subnet-cidr>, for example 10.0.1.0/24, and the NSG name:
az network nsg rule create --resource-group <your-resource-group> --nsg-name ferretdbNSG \
--name allow-ferretdb-tls --priority 1010 --access Allow --protocol Tcp --direction Inbound \
--source-address-prefixes <your-app-subnet-cidr> --destination-port-ranges 27018Never open 27018 or 27017 to the internet. The plain listener on 27017 stays on the loopback address. Copy /etc/ferretdb/tls/ferretdb.crt to the clients and use it as their CA file:
mongodb://appuser:<password>@<private-ip>:27018/?authMechanism=SCRAM-SHA-256&tls=true&tlsCAFile=/path/to/ferretdb.crtTo use a certificate from your own certificate authority instead, replace /etc/ferretdb/tls/ferretdb.crt and ferretdb.key, and restart FerretDB. Keep the key at mode 0640, owner root, group ferretdb.
Security checks
PostgreSQL accepts local socket connections with peer authentication and loopback TCP connections with SCRAM-SHA-256 only. There is no trust rule:
sudo -u postgres psql -X -At -c "SELECT type, array_to_string(user_name, ','), coalesce(address, ''), auth_method, coalesce(array_to_string(options, ','), '') FROM pg_hba_file_rules ORDER BY line_number"local|postgres||peer| local|all||peer|map=sac host|all|127.0.0.1|scram-sha-256| host|all|::1|scram-sha-256|PostgreSQL refuses a connection without a password on the TCP port, and it refuses the wrong operating system user on the socket:
R="$(psql -X -w -h 127.0.0.1 -U postgres -d postgres -c 'SELECT 1' 2>&1)" case "${R}" in *"no password supplied"*) echo "127.0.0.1:5432 as postgres, no password: refused (SCRAM-SHA-256 needs a password)" ;; *) echo "UNEXPECTED: ${R}"; exit 1 ;; esac R="$(sudo -u nobody psql -X -w -h /var/run/postgresql -U postgres -d postgres -c 'SELECT 1' 2>&1)" case "${R}" in *"Peer authentication"*) echo "socket as postgres from the OS user nobody: refused (peer authentication)" ;; *) echo "UNEXPECTED: ${R}"; exit 1 ;; esac127.0.0.1:5432 as postgres, no password: refused (SCRAM-SHA-256 needs a password) socket as postgres from the OS user nobody: refused (peer authentication)Only admin, the MongoDB user, has a password, which is stored as a SCRAM-SHA-256 verifier. PostgreSQL's own roles have none:
sudo -u postgres psql -X -c "SELECT rolname, rolsuper, left(rolpassword, 13) AS password FROM pg_authid WHERE rolcanlogin ORDER BY 1"rolname | rolsuper | password ---------------------------+----------+--------------- admin | f | SCRAM-SHA-256 documentdb_bg_worker_role | f | ferretdb | t | postgres | t | (4 rows)The image's own self test signs in as admin on both listeners, verifying this VM's certificate on the TLS one. It writes, reads, indexes and aggregates data. It also proves that FerretDB refuses all of the following:
- Wrong and empty passwords.
- Anonymous reads.
- The password-less PostgreSQL roles.
- TLS without the VM's certificate.
- Plain text on the TLS port.
Run it:
sudo /usr/local/sbin/ferretdb-roundtrip.shOK-ferretdb-scram-tls-roundtripThe certificate was generated on this VM and names its host name and its own addresses. The common name is ferretdb when the host name is longer than 64 characters. Only root and the ferretdb group can read the key:
openssl x509 -in /etc/ferretdb/tls/ferretdb.crt -noout -subject -ext subjectAltName ls -l /etc/ferretdb/tls | awk 'NR>1{print $1, $3, $4, $NF}'subject=CN = ferretdb.<dns-suffix>.bx.internal.cloudapp.net, O = sac FerretDB X509v3 Subject Alternative Name: DNS:ferretdb.<dns-suffix>.bx.internal.cloudapp.net, DNS:ferretdb, IP Address:<private-ip>, IP Address:<public-ip>, DNS:localhost, IP Address:127.0.0.1, IP Address:0:0:0:0:0:0:0:1 -rw-r--r-- root root ferretdb.crt -rw-r----- root ferretdb ferretdb.keyFerretDB, PostgreSQL and the first boot service cannot reach the Azure metadata service or the wire server. FerretDB runs sandboxed as an unprivileged user. Confirm both:
systemctl show ferretdb postgresql@17-main ferretdb-firstboot -p Id -p IPAddressDeny
systemctl show ferretdb -p User -p ProtectSystem -p ProtectHome -p NoNewPrivileges -p ReadWritePaths -p CapabilityBoundingSetIPAddressDeny=169.254.169.254/32 168.63.129.16/32 Id=ferretdb.service IPAddressDeny=169.254.169.254/32 168.63.129.16/32 Id=postgresql@17-main.service IPAddressDeny=169.254.169.254/32 168.63.129.16/32 Id=ferretdb-firstboot.service CapabilityBoundingSet= User=ferretdb ReadWritePaths=/var/lib/ferretdb/state ProtectHome=yes ProtectSystem=strict NoNewPrivileges=yesConfirm how FerretDB on this image was built:
grep -E '^(toolchain |binary sha256|govulncheck)' /usr/share/doc/ferretdb/BUILD-PROVENANCE.txttoolchain go1.27.3 linux/amd64, official tarball https://go.dev/dl/go1.27.3.linux-amd64.tar.gz toolchain sha256 65efbc80fdc1fa2cd2631cad5b481777a68e8725f34e89f50fc6ac714e379b40 binary sha256 f554a7edf6280a53ecc1a4ad1905b16d84c52da31b0bdb4fb42b85da2bcdc068 (reproducible: an independent out-of-band build of the same inputs gives the same bytes) govulncheck v1.9.0, source: No vulnerabilities found.; binary: No vulnerabilities found.Changing the administrator password
Set a new password for admin from the MongoDB shell. passwordPrompt() asks for it. Then update FERRETDB_PASSWORD in /root/ferretdb-credentials.txt, which ferretdb-shell and the self test read. If you keep the password elsewhere, delete the file instead:
sudo ferretdb-shell db.getSiblingDB("admin").updateUser("admin", {pwd: passwordPrompt()})Backup, updates and maintenance
All data is in the PostgreSQL cluster on the data disk, /var/lib/ferretdb/pg17. The simplest backup is an Azure snapshot of that disk. For a consistent copy, take the snapshot with FerretDB and PostgreSQL stopped (sudo systemctl stop ferretdb postgresql@17-main). For a backup while the services run, dump the PostgreSQL database that holds every FerretDB database:
sudo -u postgres pg_dump -Fc postgres > <backup-dir>/ferretdb-$(date +%F).dumpMongoDB's mongodump and mongorestore (MongoDB Database Tools) also work against FerretDB if you install them.
If you made the data disk larger, grow the file system once with sudo resize2fs "$(findmnt -no SOURCE /var/lib/ferretdb)".
Ubuntu security updates install automatically. PostgreSQL comes from the PGDG repository. Apply its point releases when you choose, because they restart the database (sudo apt-get update && sudo apt-get install --only-upgrade postgresql-17 postgresql-client-17). FerretDB and the DocumentDB extension are a matched pair, and a new image version updates them together.
FerretDB's settings are in /etc/ferretdb/ferretdb.env. Restart FerretDB after a change. PostgreSQL's settings are in /etc/postgresql/17/main/. The default shared_buffers is 128 MB, and on a Standard_B2s (4 GiB) about 1 GB is a good start (sudo -u postgres psql -c "ALTER SYSTEM SET shared_buffers = '1GB'" and restart PostgreSQL).
Key paths on the image (component, then path):
PostgreSQL data directory /var/lib/ferretdb/pg17 (dedicated data disk)
PostgreSQL settings /etc/postgresql/17/main/
FerretDB binary and settings /usr/local/bin/ferretdb, /etc/ferretdb/ferretdb.env
FerretDB state /var/lib/ferretdb/state
Certificate and key /etc/ferretdb/tls/ferretdb.crt, /etc/ferretdb/tls/ferretdb.key
Helpers /usr/local/bin/ferretdb-shell, /usr/local/sbin/ferretdb-tls-cert, /usr/local/sbin/ferretdb-roundtrip.sh
First boot services sac-public-ip.service, ferretdb-firstboot.service
Logs journalctl -u ferretdb, /var/log/postgresql/postgresql-17-main.log
Credentials /root/ferretdb-credentials.txt (mode 0600)
Build provenance and licences /usr/share/doc/ferretdb/, /usr/share/doc/postgresql-17-documentdb/LICENSE, /opt/mongosh-2.13.0/
Security recommendations
- Allow port 22 from your admin network only. Keep 27017 on the loopback address. If applications need to connect, open the TLS port 27018 to their subnet only (Step 9), never to the internet. Never open 5432.
- Remember that FerretDB authenticates users but does not yet enforce their roles, so anyone who signs in can read and write everything. Treat every FerretDB password as an administrator password.
- Give clients the VM's certificate as their CA file, or issue a certificate from your own CA.
- Change the administrator password if it may have been shared (Step 11), and snapshot the data disk regularly.
Support and licensing
SecureAnyCloud provides 24/7 expert support for this image by email at sales@secureanycloud.com. Include the VM name, the image (FerretDB on Ubuntu 24.04 LTS) and what you were doing.
FerretDB is open source software under the Apache License 2.0, the DocumentDB extension is under the MIT License, PostgreSQL is under the PostgreSQL License and mongosh is under the Apache License 2.0. The licences are on the VM. There is no per-user or per-CPU licence fee. The SecureAnyCloud charge covers the hardening, first boot setup, image maintenance and support.
FerretDB is a trademark of FerretDB Inc. MongoDB and MongoDB Compass are trademarks of MongoDB, Inc. PostgreSQL is a trademark of the PostgreSQL Community Association of Canada. Ubuntu is a trademark of Canonical Ltd. All other names are trademarks of their respective owners. SecureAnyCloud is not affiliated with or endorsed by these organisations.
Deploy on Azure
Launch FerretDB on Ubuntu 24.04 LTS on Azure with 24/7 support from SecureAnyCloud.
View this image
Need Help?
Our support team is available 24/7.
sales@secureanycloud.com
Overview
FerretDB is an open source document database that is compatible with the MongoDB wire protocol. It lets you keep using MongoDB drivers, the mongosh shell and the MongoDB query and aggregation language, while your data is stored in PostgreSQL through the DocumentDB extension.
This image is a ready-to-use database appliance on Amazon EC2. postgresql.service and ferretdb.service are enabled and start on boot, so the MongoDB-compatible endpoint is already answering when you connect over SSH.
What you get:
- A headless database service with no web interface. FerretDB speaks the MongoDB wire protocol on the loopback interface (
127.0.0.1:27017) and exposes its debug and metrics HTTP handlers on loopback (127.0.0.1:8088). The shipped security group opens port 22 only, so neither is exposed to the network. - A strong, unique database password, generated automatically on the first boot of every instance and written to a root-only credentials file. No shared secret is baked into the image. Clients authenticate against PostgreSQL using SCRAM-SHA-256.
- A PostgreSQL data directory relocated onto a dedicated, independently resizable EBS data volume mounted at
/var/lib/ferretdb. The database grows on durable storage that you can expand without touching the boot volume. - The DocumentDB extension, already created in the backend database and ready for your first collection.
Prerequisites
Before you deploy this image, you need:
- An Amazon Web Services account where you can launch EC2 instances.
- IAM permissions to launch instances, create security groups and subscribe to AWS Marketplace products.
- An EC2 key pair in the target Region for SSH access to the instance.
- A VPC and subnet in the target Region, with a security group that allows inbound port 22 from your management network.
- The AWS CLI (version 2) installed locally, if you plan to deploy from the command line.
Launch the Instance from the AWS Marketplace
Sign in to the AWS Management Console, open the EC2 service, and choose Launch instance. Under Application and OS Images, choose AWS Marketplace AMIs and search for FerretDB. Select the SecureAnyCloud listing, choose Select, then choose Continue on the subscription summary.
Pick an instance type of t3.medium or larger. Choose your EC2 key pair under Key pair (login). Under Network settings, select your VPC and subnet, and create or select a security group that opens port 22 from your management network. Leave the root volume at the default size or larger.
Choose Launch instance. First boot initialisation takes a short time after the instance state becomes Running and the status checks pass. The image generates the per-instance database password, creates the PostgreSQL role and starts FerretDB against it.
Launch the Instance from the AWS CLI
This command launches an instance from the SecureAnyCloud FerretDB Marketplace AMI into an existing subnet and security group. Make these replacements:
- Replace <ami-id> with the AMI ID shown on the Marketplace listing.
- Replace <key-name> with your EC2 key pair name.
- Replace <subnet-id> with your subnet ID.
- Replace <security-group-id> with a security group that opens port 22 from your management network.
aws ec2 run-instances \
--image-id <ami-id> \
--instance-type t3.medium \
--key-name <key-name> \
--subnet-id <subnet-id> \
--security-group-ids <security-group-id> \
--tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=ferretdb}]'When the instance reaches the Running state and its status checks pass, note its public IP address or DNS name. You can find it in the EC2 console or with aws ec2 describe-instances.
Connect to Your Instance
Connect over SSH using your key pair. The SSH login user for the Debian 12 variant is admin:
ssh -i <key-name>.pem admin@<public-ip>A welcome banner prints the most useful commands. The per-instance database password and a ready-to-paste connection string are in a root-only credentials file:
sudo cat /root/ferretdb-credentials.txtThis file contains the generated ferretdb.password, the mongosh connection string, and notes on the services, the debug endpoint and the data directory. The password is unique to this instance and is created on first boot, so nothing is shared across deployments.
Verify the Services
FerretDB and its PostgreSQL backend run as system services that are enabled and start on boot. Confirm that both are active:
systemctl is-active postgresql ferretdbEach line prints active. To see the full unit status of FerretDB, including the main PID and memory use, run:
systemctl status ferretdb --no-pagerConfirm the installed binary and version. This image runs FerretDB 2.7.0:
ferretdb --versionThe output reports version 2.7.0. The ferretdb binary is installed at /usr/bin/ferretdb and is on the system path.
Connect with the MongoDB Shell
FerretDB speaks the MongoDB wire protocol on the loopback interface (127.0.0.1:27017), and the image ships the MongoDB shell, mongosh. Read the generated password into a shell variable, then connect:
PASS=$(sudo grep '^ferretdb.password=' /root/ferretdb-credentials.txt | cut -d= -f2-) mongosh "mongodb://ferretdb:${PASS}@127.0.0.1:27017/" --quiet --eval 'db.runCommand({ping:1})'The output is { ok: 1 }, which confirms that the MongoDB-compatible endpoint is answering and that your credentials authenticated against PostgreSQL. Insert a document into a collection and read it back, exactly as you would with MongoDB:
PASS=$(sudo grep '^ferretdb.password=' /root/ferretdb-credentials.txt | cut -d= -f2-) mongosh "mongodb://ferretdb:${PASS}@127.0.0.1:27017/" --quiet --eval ' var d = db.getSiblingDB("appdb"); d.products.insertOne({ name: "widget", price: 9.99, tags: ["new", "sale"] }); printjson(d.products.find().toArray()); 'The document round-trips through FerretDB into PostgreSQL, and the find returns it. You can use collections, indexes, the aggregation pipeline and the rest of the MongoDB query language. FerretDB translates every operation to SQL and persists it in the backend.
The Debug and Metrics Endpoint
FerretDB exposes a debug HTTP handler on loopback (127.0.0.1:8088). The liveness probe returns HTTP 200 when FerretDB is ready to accept connections.
curl -fsS -o /dev/null -w '%{http_code}\n' http://127.0.0.1:8088/debug/livezThe command prints 200. The readiness probe also confirms that a backend PostgreSQL connection can be established:
curl -fsS -o /dev/null -w '%{http_code}\n' http://127.0.0.1:8088/debug/readyzPrometheus-format metrics are served at /debug/metrics for scraping:
curl -fsS http://127.0.0.1:8088/debug/metrics | grep -E '^ferretdb_|^go_goroutines'The PostgreSQL Backend and Data Volume
FerretDB stores all data in PostgreSQL 17 through the DocumentDB extension. The PostgreSQL data directory lives on a dedicated EBS volume mounted at /var/lib/ferretdb. This keeps the database off the operating system disk, so you can resize or snapshot it independently. Confirm the mount:
df -h /var/lib/ferretdbThe DocumentDB extension is already created in the backend postgres database. Confirm it directly:
sudo -u postgres psql -tAc "SELECT extname FROM pg_extension WHERE extname='documentdb';"The command prints documentdb. To grow the volume, expand the EBS volume in the AWS console, then grow the filesystem on the instance with sudo resize2fs on the underlying device.
Serving Remote Clients
By default, FerretDB binds the MongoDB-compatible endpoint to loopback only, and the security group opens port 22 alone, so the database is private to the instance. To serve remote clients:
- Bind FerretDB to an external address by overriding the listen address. Set
FERRETDB_LISTEN_ADDR=0.0.0.0:27017withsudo systemctl edit ferretdb, then runsudo systemctl restart ferretdb. - Open port 27017 in the instance security group to your trusted CIDR only.
- Front the endpoint with TLS.
Point your application's MongoDB connection string at the instance, using the same ferretdb user and generated password.
Support
SecureAnyCloud publishes and supports this image. Support covers connection strings and drivers, authentication and roles, indexes and the aggregation pipeline, the PostgreSQL backend and the DocumentDB extension, backups, capacity planning and upgrade planning. Contact SecureAnyCloud through the support channel listed on the AWS Marketplace listing.
All product and company names are trademarks or registered trademarks of their respective holders. Use of them does not imply any affiliation with or endorsement by them.
Deploy on AWS
Launch FerretDB on AWS with 24/7 support from SecureAnyCloud.
View on Marketplace
Need Help?
Our support team is available 24/7.
sales@secureanycloud.com