> ## Documentation Index
> Fetch the complete documentation index at: https://docs.minimus.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Mongo TLS Tutorial

> A guide to setting up Mongo and testing that it accepts TLS connections, enforces authentication, and allows secure read/write operations from a test client

The following guide will help you deploy the Minimus Mongo image with self-signed, locally issued certificates to help you get started. Run the code to try it for yourself.

<Info>
  For production purposes, we recommend using publicly trusted certificates issued by a Certificate Authority (CA).
</Info>

## Components

* **Mongo image built by Minimus**: MongoDB container running with `requireTLS` and client authentication.
* **mongosh** installed.
* Dynamic certificate generation via OpenSSL:
  * **certgen.sh script**: Shell script that generates a custom CA, server, and client certificates using OpenSSL.
  * **minidebug image**: A Minimus dev toolkit that provides a shell, OpenSSL, and other utilities used to generate the certificates.

## What this guide demonstrates

* TLS handshake validation
* Server/client certificate trust
* Basic auth and MongoDB operations
* Image compatibility

## Directory Structure

```bash theme={null}
.
├── certgen.sh             # Certificate generation script
├── create-certs.yml       # Compose file to run certgen container
└── docker-compose.yml     # Compose file to run MongoDB
```

## Deploy Mongo with TLS certificates

### Prerequisite: Authenticate to the Minimus Registry

Run the docker login command to authenticate to the Minimus registry:

```shellscript theme={null}
echo "{token}" | docker login reg.mini.dev -u minimus --password-stdin
```

### Step 1: Generate TLS certificates

<Steps>
  <Step title="Save script that generates TLS certificates">
    Save the following script to a file named `certgen.sh`. The script is used to generate the TLS certificates and store them in a `certs` folder on the host.

    ```bash certgen.sh expandable theme={null}
    #!/bin/sh

    set -e
    cd /certs

    echo "[INFO] Generating OpenSSL config..."
    cat > openssl.cnf <<EOF
    [req]
    distinguished_name = req_distinguished_name
    prompt = no

    [req_distinguished_name]
    CN = mongo

    [v3_req]
    keyUsage = keyEncipherment, dataEncipherment
    extendedKeyUsage = serverAuth
    subjectAltName = @alt_names

    [v3_client]
    keyUsage = digitalSignature
    extendedKeyUsage = clientAuth
    subjectAltName = @alt_names

    [v3_ca]
    subjectKeyIdentifier = hash
    authorityKeyIdentifier = keyid:always,issuer
    basicConstraints = critical, CA:true
    keyUsage = critical, keyCertSign, cRLSign

    [alt_names]
    DNS.1 = mongo
    DNS.2 = localhost
    IP.1 = 127.0.0.1
    IP.2 = 192.168.50.0
    IP.3 = 192.168.50.2
    IP.4 = 192.168.50.3


    EOF

    echo "[INFO] Creating CA certificate..."
    openssl genrsa -out ca-key.pem 2048
    openssl req -x509 -new -nodes -key ca-key.pem -sha256 -days 365 \
      -out ca.pem -subj "/CN=MongoDB Test CA" \
      -extensions v3_ca -config openssl.cnf

    echo "[INFO] Creating server certificate..."
    openssl genrsa -out server-key.pem 2048
    openssl req -new -key server-key.pem -out server.csr \
      -config openssl.cnf -extensions v3_req
    openssl x509 -req -in server.csr -CA ca.pem -CAkey ca-key.pem -CAcreateserial \
      -out server-cert.pem -days 365 -sha256 \
      -extfile openssl.cnf -extensions v3_req
    cat server-cert.pem server-key.pem > server.pem

    echo "[INFO] Creating client certificate..."
    openssl genrsa -out client-key.pem 2048
    openssl req -new -key client-key.pem -out client.csr -subj "/CN=root"
    openssl x509 -req -in client.csr -CA ca.pem -CAkey ca-key.pem -CAcreateserial \
      -out client-cert.pem -days 365 -sha256 \
      -extfile openssl.cnf -extensions v3_client
    cat client-cert.pem client-key.pem > client.pem
    ls -l /certs/
    echo "[INFO] Adjusting permissions..."

    # Secure private keys
    [ -f server-key.pem ] && chmod 600 server-key.pem
    [ -f client-key.pem ] && chmod 600 client-key.pem

    # Public certs readable
    chmod 644 ca.pem server-cert.pem client-cert.pem server.pem client.pem

    # Ownership
    chown -R 1000:1000 /certs/*.pem || echo "[WARN] chown failed (non-root?)"

    # Final check
    for f in ca.pem server.pem client.pem; do
      [ -f "/certs/$f" ] || { echo "[ERROR] Missing: $f"; exit 1; }
    done

    echo "[SUCCESS] Certificates generated for MongoDB."
    ```
  </Step>

  <Step title="Save Docker Compose configuration">
    Save the following YAML file to run with Docker Compose. It uses the [**Minimus minidebug image**](https://images.minimus.io/gallery/images/minidebug/quick-start?__hstc=180987128.11065ee83c8bdcec1851176c12d849d3.1762436227738.1762436227738.1762436227738.1&__hssc=180987128.1.1762436227739&__hsfp=2666866004) to generate the certificates with the `certgen.sh` shell script. Minidebug is a Minimus dev toolkit that provides a shell, OpenSSL, and other utilities. The certificates will be persisted in the `certs` volume on the host.

    ```yaml create-certs.yml theme={null}
    services:
      certgen:
        image: reg.mini.dev/minidebug:latest
        container_name: mongo_certgen
        volumes:
        - ./certs:/certs
        - ./certgen.sh:/certgen.sh:ro
        entrypoint:
        - /bin/sh
        - /certgen.sh
        network_mode: none
    ```
  </Step>

  <Step title="Generate certificates">
    Run the following to generate the certificates:

    ```shellscript theme={null}
    docker compose -f create-certs.yml up
    ```
  </Step>
</Steps>

Congrats! You have just generated the following self-signed certificates:

* CA certificate (`ca.pem`)
* Server certificates (`server-cert.pem`, `server-key.pem`)
* Client certificates (`client.pem`, `client-key.pem`)

The setup ensures:

* Proper SANs for `mongo` and `localhost`
* Client certs with `clientAuth`
* Server certs with `serverAuth`

In the next steps, you will mount these certificates into the Mongo container.

### Step 2: Deploy Mongo server

<Steps>
  <Step title="Save Mongo Compose script">
    Save the following Docker Compose script to a file named `docker-compose.yml`. This script sets up the Mongo service with a healthcheck, mounts a volume with the certificates, maps port 27017, and connects the container to a custom network.

    ```yaml docker-compose expandable theme={null}
    services:
      mongo:
        image: reg.mini.dev/mongo:latest
        container_name: mongo_tls
        healthcheck:
          test: ["CMD", "mongosh", "--tls", "--tlsCAFile", "/certs/ca.pem", "--tlsCertificateKeyFile", "/certs/server.pem", "--eval", "db.adminCommand('ping')"]
          interval: 5s
          timeout: 3s
          retries: 10
        environment:
          MONGO_INITDB_ROOT_USERNAME: root
          MONGO_INITDB_ROOT_PASSWORD: rootpass
          MONGO_INITDB_DATABASE: testdb
        volumes:
          - ./certs:/certs:ro
          - mongo_data:/data/db
        ports:
          - "27017:27017"
        command: [
          "mongod",
          "--auth",
          "--bind_ip_all",
          "--tlsMode", "requireTLS",
          "--tlsCertificateKeyFile", "/certs/server.pem",
          "--tlsCAFile", "/certs/ca.pem"
        ]

    volumes:
      mongo_data:
    ```
  </Step>

  <Step title="Run Mongo">
    Start the Mongo container:

    ```shellscript theme={null}
    docker compose -f docker-compose.yml up
    ```
  </Step>
</Steps>

### Step 3: Test your Mongo server

We will use mongosh, the mongo shell, to connect over HTTPS and run tests. For example, here are a few commands you can try out:

1. Check db health
   ```bash theme={null}
   mongosh "mongodb://root@localhost:27017/admin?authMechanism=SCRAM-SHA-256" \
   --tls \
   --tlsCAFile ./certs/ca.pem \
   --tlsCertificateKeyFile ./certs/client.pem \
   --eval 'db.adminCommand("ping")' \
   --password rootpass
   ```
   You should get the response `{ ok: 1 }`.
2. Create a test database (for example `testdb`):

   <CodeGroup>
     ```shellscript Create database theme={null}
       mongosh "mongodb://root@localhost:27017/admin?authMechanism=SCRAM-SHA-256" \
         --tls \
         --tlsCAFile ./certs/ca.pem \
         --tlsCertificateKeyFile ./certs/client.pem \
         --password rootpass \
         --eval '
       const dbname = "testdb";
       const testdb = db.getSiblingDB(dbname);
       const result = testdb.sample.insertOne({ createdAt: new Date(), msg: "Hello from mongosh over TLS" });
       print("✅ Created database:", dbname);
       printjson(result);
       '
     ```

     ```bash Expected response theme={null}
     ✅ Created database: testdb
     {
       acknowledged: true,
       insertedId: ObjectId('6910880f1508c964cfb69764')
     }
     ```
   </CodeGroup>
3. List all databases.
   <CodeGroup>
     ```bash List all databases theme={null}
       mongosh "mongodb://root@localhost:27017/admin?authMechanism=SCRAM-SHA-256" \
         --tls \
         --tlsCAFile ./certs/ca.pem \
         --tlsCertificateKeyFile ./certs/client.pem \
         --password rootpass \
         --eval '
       const res = db.adminCommand({ listDatabases: 1 });
       printjson(res);
       '    
     ```
   </CodeGroup>
4. Create document in `testdb.docs`:
   ```bash theme={null}
     mongosh "mongodb://root@localhost:27017/admin?authMechanism=SCRAM-SHA-256" \
       --tls \
       --tlsCAFile ./certs/ca.pem \
       --tlsCertificateKeyFile ./certs/client.pem \
       --password rootpass \
       --eval '
     const now = new Date().toISOString();
     const res = db.getSiblingDB("testdb").docs.insertOne({
       test: "Welcome to TLS MongoDB running on a Minimus image",
       timestamp: now
     });
     printjson(res);
     '
   ```
5. Create a user (for example, `testuser` with `readWrite` role on `testdb`), get user details, and delete the user:

   <CodeGroup>
     ```bash Create user theme={null}
     mongosh "mongodb://root@localhost:27017/admin?authMechanism=SCRAM-SHA-256" \
       --tls \
       --tlsCAFile ./certs/ca.pem \
       --tlsCertificateKeyFile certs/client.pem \
       --password rootpass \
       --eval '
     printjson(db.getSiblingDB("admin").createUser({
       user: "testuser",
       pwd: "testpass",
       roles: [ { role: "readWrite", db: "testdb" } ]
     }));
     '
     ```

     ```bash Get user details theme={null}
     mongosh "mongodb://root@localhost:27017/admin?authMechanism=SCRAM-SHA-256" \
       --tls \
       --tlsCAFile ./certs/ca.pem \
       --tlsCertificateKeyFile ./certs/client.pem \
       --password rootpass \
       --eval '
     printjson(db.getSiblingDB("admin").getUser("testuser"));
     '
     ```

     ```bash Delete user theme={null}
     mongosh "mongodb://root@localhost:27017/admin?authMechanism=SCRAM-SHA-256" \
       --tls \
       --tlsCAFile ./certs/ca.pem \
       --tlsCertificateKeyFile ./certs/client.pem \
       --password rootpass \
       --eval '
     printjson(db.getSiblingDB("admin").dropUser("testuser"));
     '
     ```
   </CodeGroup>
6. Insert a new document:
   <CodeGroup>
     ```bash Insert document theme={null}
     mongosh "mongodb://root@localhost:27017/admin?authMechanism=SCRAM-SHA-256" \
       --tls \
       --tlsCAFile ./certs/ca.pem \
       --tlsCertificateKeyFile ./certs/client.pem \
       --password rootpass \
       --eval '
     const dbname = "testdb";
     const coll = db.getSiblingDB(dbname).docs;
     const doc = {
       test: "Welcome to TLS MongoDB running Minimus image",
       timestamp: new Date().toISOString()
     };
     print("✅ Inserting document:");
     printjson(doc);
     printjson(coll.insertOne(doc));
     ' 
     ```
   </CodeGroup>
7. Get all documents in a collection:
   ```bash theme={null}
   mongosh "mongodb://root@localhost:27017/admin?authMechanism=SCRAM-SHA-256" \
     --tls \
     --tlsCAFile ./certs/ca.pem \
     --tlsCertificateKeyFile ./certs/client.pem \
     --password rootpass \
     --eval '
   const dbname = "testdb";
   const coll = db.getSiblingDB(dbname).docs;
   print("📄 All documents in", dbname + ".docs:");
   coll.find().forEach(doc => printjson(doc));
   '
   ```
8. Delete a database:
   <CodeGroup>
     ```bash Drop database theme={null}
     mongosh "mongodb://root@localhost:27017/admin?authMechanism=SCRAM-SHA-256" \
       --tls \
       --tlsCAFile ./certs/ca.pem \
       --tlsCertificateKeyFile ./certs/client.pem \
       --password rootpass \
       --eval '
     const dbname = "testdb";
     const res = db.getSiblingDB(dbname).dropDatabase();
     print("🗑️ Dropped database:", dbname);
     printjson(res);
     ' 
     ```
   </CodeGroup>
