Skip to content

FerretDB® (self-managed)

Warning

This page provides a starting point for installing an application. The information is useful, but not kept up-to-date. If you struggle, contact Elastisys Consulting.

This page describes how to install a Customer Application

You are solely responsible for Customer Applications.

If you are an Elastisys Managed Services customer, please review your responsibilities in ToS 5.2.

Specifically, you are responsible for performing due diligence for the project discussed in this page. At the very least, you must:

  • assess project ownership, governance and licensing;
  • assess project roadmap and future suitability;
  • assess project compatibility with your use-case;
  • assess business continuity, i.e., what will you do if the project is abandoned;
  • subscribe to security advisories related to the project;
  • apply security patches and updates, as needed;
  • regularly test disaster recovery.

Danger

FerretDB® tries to be a drop-in replacement for MongoDB®. However:

Make sure to load-test your application with FerretDB before going into production.

FerretDB is a database that is an open-source alternative to MongoDB that uses PostgreSQL as its backend database. This documentation details how to run FerretDB in a Welkin cluster using the Managed PostgreSQL service.

Pushing FerretDB image to Harbor

These instructions will pull the FerretDB container image and push it to another registry. If you are using managed Harbor as your container registry, please follow these instructions on how to authenticate, create a new project, and how to create a robot account and using it in a pull-secret to be able to pull an image from Harbor to your cluster safely:

TAG=1.0.0
REGISTRY=harbor.$DOMAIN
REGISTRY_PROJECT=demo

docker pull ghcr.io/ferretdb/ferretdb:$TAG
docker tag ghcr.io/ferretdb/ferretdb:$TAG $REGISTRY/$REGISTRY_PROJECT/ferretdb:$TAG
docker push $REGISTRY/$REGISTRY_PROJECT/ferretdb:$TAG

Install

In a managed Welkin environment, follow these instructions on how to access the Managed PostgreSQL service and how to create an application user and database.

Create secret containing a PostgreSQL URL to authenticate to the Managed PostgreSQL service and newly created database with the application user credentials:

kubectl create secret generic --from-literal=ferretdb-url="postgresql://$APP_USERNAME:$APP_PASSWORD@$PGHOST:$PGPORT/$APP_DATABASE" ferretdb-postgres-credentials

Deploy:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: ferretdb
  labels:
    run: ferretdb
spec:
  replicas: 1
  selector:
    matchLabels:
      run: ferretdb
  template:
    metadata:
      labels:
        run: ferretdb
    spec:
      containers:
        - name: ferretdb
          image: $REGISTRY/$REGISTRY_PROJECT/ferretdb:$TAG # replace this
          args:
            - --listen-addr=0.0.0.0:27017
            - --telemetry=disable
            - --postgresql-url=$(FERRETDB_URL)
          env:
            - name: FERRETDB_URL
              valueFrom:
                secretKeyRef:
                  name: ferretdb-postgres-credentials
                  key: ferretdb-url
          resources:
            requests:
              cpu: "1000m"
              memory: "15M"
          securityContext:
            capabilities:
              drop:
                - ALL
            runAsNonRoot: true
            runAsUser: 1001
          volumeMounts:
            - mountPath: /state
              name: state
      securityContext:
        fsGroup: 1001
      volumes:
        - name: state
          emptyDir: {}
---
apiVersion: v1
kind: Service
metadata:
  name: ferretdb-service
  labels:
    run: ferretdb
spec:
  type: ClusterIP
  selector:
    run: ferretdb
  ports:
    - protocol: TCP
      port: 27017
      targetPort: 27017

Check that FerretDB started properly:

$ kubectl get svc,deploy,pod -l run=ferretdb
NAME                       TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)     AGE
service/ferretdb-service   ClusterIP   10.233.42.102   <none>        27017/TCP   75s

NAME                       READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/ferretdb   1/1     1            1           75s

NAME                            READY   STATUS    RESTARTS   AGE
pod/ferretdb-5887cc848c-brwjf   1/1     Running   0          75s

The Deployment should show STATUS is Running. The Pod(s) should have STATUS is Running.

To try out access to FerretDB, you can port-forward the Service to localhost and connect using mongosh:

kubectl port-forward svc/ferretdb-service 27017

mongosh mongodb://localhost:27017

Python client example

The following is an example of how to connect to FerretDB using the PyMongo Python library (using the localhost port-forwarding described above).

from pymongo import MongoClient

client = MongoClient('mongodb://localhost:27017')

# List all databases
print(client.list_database_names())

# List collections in the database "mongodb"
print(client['mongodb'].list_collection_names())

# Create db and insert element into a collection
database   = client['test_db']
collection = database['customers']

mydict = { "name": "John", "address": "Highway 38" }

collection.insert_one(mydict)
print(collection.find_one())

See the following pg_dump below to see how the example above is mapped in the actual backend PostgreSQL database.

`pg_dump`
--
-- PostgreSQL database dump
--

-- Dumped from database version 14.6 (Ubuntu 14.6-1.pgdg22.04+1)
-- Dumped by pg_dump version 15.1 (Ubuntu 15.1-1.pgdg22.04+1)

SET statement_timeout = 0;
SET lock_timeout = 0;
SET idle_in_transaction_session_timeout = 0;
SET client_encoding = 'UTF8';
SET standard_conforming_strings = on;
SELECT pg_catalog.set_config('search_path', '', false);
SET check_function_bodies = false;
SET xmloption = content;
SET client_min_messages = warning;
SET row_security = off;

--
-- Name: test_db; Type: SCHEMA; Schema: -; Owner: ferretdb
--

CREATE SCHEMA test_db;


ALTER SCHEMA test_db OWNER TO ferretdb;

SET default_tablespace = '';

SET default_table_access_method = heap;

--
-- Name: _ferretdb_database_metadata; Type: TABLE; Schema: test_db; Owner: ferretdb
--

CREATE TABLE test_db._ferretdb_database_metadata (
    _jsonb jsonb
);


ALTER TABLE test_db._ferretdb_database_metadata OWNER TO ferretdb;

--
-- Name: customers_c09344de; Type: TABLE; Schema: test_db; Owner: ferretdb
--

CREATE TABLE test_db.customers_c09344de (
    _jsonb jsonb
);


ALTER TABLE test_db.customers_c09344de OWNER TO ferretdb;

--
-- Data for Name: _ferretdb_database_metadata; Type: TABLE DATA; Schema: test_db; Owner: ferretdb
--

COPY test_db._ferretdb_database_metadata (_jsonb) FROM stdin;
{"$s": {"p": {"_id": {"t": "string"}, "table": {"t": "string"}, "indexes": {"i": [{"t": "object", "$s": {"p": {"key": {"t": "object", "$s": {"p": {"_id": {"t": "int"}}, "$k": ["_id"]}}, "name": {"t": "string"}, "unique": {"t": "bool"}, "pgindex": {"t": "string"}}, "$k": ["pgindex", "name", "key", "unique"]}}], "t": "array"}}, "$k": ["_id", "table", "indexes"]}, "_id": "customers", "table": "customers_c09344de", "indexes": [{"key": {"_id": 1}, "name": "_id_", "unique": true, "pgindex": "customers__id__e06693c2_idx"}]}
\.


--
-- Data for Name: customers_c09344de; Type: TABLE DATA; Schema: test_db; Owner: ferretdb
--

COPY test_db.customers_c09344de (_jsonb) FROM stdin;
{"$s": {"p": {"_id": {"t": "objectId"}, "name": {"t": "string"}, "address": {"t": "string"}}, "$k": ["_id", "name", "address"]}, "_id": "6454cd232da4567e5cd31f39", "name": "John", "address": "Highway 37"}
\.


--
-- Name: _ferretdb_database_metadata_id_idx; Type: INDEX; Schema: test_db; Owner: ferretdb
--

CREATE UNIQUE INDEX _ferretdb_database_metadata_id_idx ON test_db._ferretdb_database_metadata USING btree (((_jsonb -> '_id'::text)));


--
-- Name: customers__id__e06693c2_idx; Type: INDEX; Schema: test_db; Owner: ferretdb
--

CREATE UNIQUE INDEX customers__id__e06693c2_idx ON test_db.customers_c09344de USING btree (((_jsonb -> '_id'::text)));


--
-- PostgreSQL database dump complete
--

Security

FerretDB supports securing connections between FerretDB and client with TLS. All you need is to specify additional run-time arguments or environment variables, as described in the FerretDB documentation.

Known Issues / Limitations

  • FerretDB currently does not support user management.
  • FerretDB currently does not support role management.
  • FerretDB currently does not allow for optimizations or tweaks to the underlying PostgreSQL schema that is used by FerretDB as it translates MongoDB collections to PostgreSQL tables.

Note
As of May 2023, the project was recently released to its first major version (v1.0.0) and is constantly being developed and improved, hence, these issues may have already been solved depending on when you are reading this. Check supported commands for FerretDB to see what is currently available.

Further Reading