Skip to main content
Set up CouchDB and test that CouchDB accepts TLS connections, enforces authentication, and allows secure read/write operations from a test client.

Components

  • CouchDB image: CouchDB listens only on HTTPS (5984); HTTP is disabled.
  • certgen.sh script: 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.
The test does not persist any certificates on the host machine.

What this guide demonstrates:

  • TLS handshake validation
  • Server/client certificate trust
  • Basic auth and CouchDB operations

Directory Structure

.
├── certgen.sh              # Script to generate CA, server, and client certs
├── create-certs.yml        # Compose file to generate certs in a dedicated container
├── couchdb-local.ini       # CouchDB configuration with SSL and authentication
└── docker-compose.yml      # Compose file for CouchDB and test client

Deploy CouchDB with TLS certificates

1

Save certgen.sh

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.
certgen.sh
#!/bin/sh
# Company: Minimus

set -e
cd /certs

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

[req_distinguished_name]
CN = couchdb

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

[alt_names]
DNS.1 = couchdb
DNS.2 = localhost
IP.1 = 127.0.0.1
IP.2 = 192.168.80.0
IP.3 = 192.168.80.2
IP.4 = 192.168.80.3


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

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

echo "[INFO] Creating server cert..."
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 ca.pem > server.pem

echo "[INFO] Creating client cert..."
openssl genrsa -out client-key.pem 2048
openssl req -new -key client-key.pem -out client.csr -subj "/CN=couchdb-client"
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_req
cat client-cert.pem client-key.pem > client.pem
cat server-cert.pem ca.pem > server.pem

echo "[INFO] Setting file ownership and permissions..."
chown 1000:1000 /certs/*.pem || echo "[WARN] chown failed"
chmod 600 /certs/*-key.pem
chmod 644 /certs/*.pem

echo "[SUCCESS] Certificates successfully created for CouchDB."
2

Save create-certs.yml

Save the following YAML file to run with Docker Compose. It uses the Minimus minidebug image to generate the certificates with the certgen.shshell 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.
create-certs.yml
services:
  certgen:
    image: reg.mini.dev/minidebug:latest
    container_name: certgen
    volumes:
    - ./certs:/certs
    - ./certgen.sh:/certgen.sh:ro
    entrypoint:
    - /bin/sh
    - /certgen.sh
    network_mode: none
3

Generate certificates

Run the following to generate the certificates:
docker compose -f create-certs.yml up

TLS certificates

The script certgen.sh generates the following self-signed certificates:
  • CA certificate (ca.pem)
  • Server certificates (server-cert.pem, server-key.pem)
  • Client certificates (client.pem, client-key.pem)
These certificates will be mounted into the CouchDB container and configured via local.ini.
4

Save couchdb-local.ini

Save the following configuration to a file named couchdb-local.ini:
couchdb-local.ini
[couchdb] 
single_node = true

[cluster]
n = 1
q = 8

[chttpd_auth_lockout]
mode = off

[chttpd]
; Disable plain HTTP completely by setting an invalid port
port = 0
bind_address = 0.0.0.0
require_valid_user = true

[daemons]
; Enable only HTTPS daemon
httpsd = {couch_httpd, start_link, ["https"]}
; Optionally comment out httpd if not used:
; httpd = {couch_httpd, start_link, ["http"]}

[ssl]
; Now safe to bind to 5984 since HTTP is disabled
port = 5984
enable = true
cert_file = /certs/server-cert.pem
key_file = /certs/server-key.pem
cacert_file = /certs/ca.pem
verify_ssl_certificates = true
verify_ssl_peer = true
fail_if_no_peer_cert = false

[admins]
admin = admin

[authentication]
authentication_handlers = {chttpd_auth, proxy_authentication_handler}, {chttpd_auth, default_authentication_handler}

# Use TLS 1.2+
tls_versions = tlsv1.2,tlsv1.3
5

Save Docker Compose script

Save the following Docker Compose script to docker-compose.yml. This compose file sets up CouchDB using TLS (HTTPS only), with authentication enabled, mounts the generated certificates, uses the configurations in the local INI file, and exposes CouchDB over https://localhost:15984.
docker-compose.yml
services:
  couchdb:
    image: reg.mini.dev/couchdb:latest-dev
    container_name: couchdb-1
    environment:
      - COUCHDB_USER=admin
      - COUCHDB_PASSWORD=admin
      - NODENAME=couchdb
      - COUCHDB_CLUSTER_SIZE=1
    volumes:
      - ./certs:/certs
      - ./data:/opt/couchdb/data
      - ./couchdb-local.ini:/opt/couchdb/etc/local.ini
    ports:
      - "15984:5984"
If you don’t yet have the folder ./data ready and waiting, create it and give it permissions:
mkdir data
sudo chmod -R 777 ./data
6

Run CouchDB

Start the CouchDB container:
docker compose -f docker-compose.yml up --build -d
7

Run tests over HTTPS

Connect to the database and test connectivity. For example, here are a few commands you can try out:
  1. Check server health:
    curl --cacert certs/ca.pem -u admin:admin https://localhost:15984/_up
    
    You should get the response {"seeds":{},"status":"ok"}.
  2. Create and delete a database (for example testdb):
    curl --cacert certs/ca.pem \
         -u admin:admin \
         -X PUT \
         https://localhost:15984/testdb
    
  3. List all databases:
    curl --cacert certs/ca.pem -u admin:admin https://localhost:15984/_all_dbs
    
    You can also pass the request for a JSON format. This option requires the jq JSON processor.
    curl --cacert certs/ca.pem -u admin:admin https://localhost:15984/_all_dbs | jq .
    
  4. Check if a database exists:
    curl --cacert certs/ca.pem \
    -u admin:admin https://localhost:15984/testdb
    
  5. Create document:
    curl --cacert certs/ca.pem \
         -u admin:admin \
         -X PUT \
         -H "Content-Type: application/json" \
         -d '{
           "test": "Welcome to TLS couchdb running Minimus image",
           "timestamp": "'$(date -u +"%Y-%m-%dT%H:%M:%SZ")'"
         }' \
         https://localhost:15984/testdb/doc1
    
Last modified on January 28, 2026