Join our Newsletter — 33% off our NHI Course
Home› Guides› Apache CouchDB Security: Admins, Erlang Cookies, TLS and…
Guide Data Security

Apache CouchDB Security: Admins, Erlang Cookies, TLS and Safe Binding

← All guides
By NHI Mgmt Group, edited by Lalit Choda Updated 8 November 2026 14 min read
On this page

Apache CouchDB speaks plain HTTP and JSON on port 5984, so every setting that decides who can reach it, who can log in and what each identity can touch is a customer-side choice that needs to be made deliberately. CouchDB 3.x gives operators a solid set of controls: a mandatory server admin at startup, admin-only new databases, per-database _security objects, cookie, proxy and JWT authentication, built-in TLS and a shared Erlang cookie that protects cluster traffic. This guide shows how to use them together: network binding and ports, server admins, users and roles, database authorisation, replication and service credentials, logging and a hardening baseline you can roll out in phases. It is written for platform engineers, DBAs and security architects who run self-managed CouchDB, and it goes deeper than the general Database Security Guide.

This is an independent guide from NHI Mgmt Group, based on Apache CouchDB's public documentation as of November 2026. It is not sponsored or reviewed by the Apache CouchDB project. Product features change, so confirm settings against Apache CouchDB's current documentation.

Key takeaways

  • Admin Party is over in 3.x. Since CouchDB 3.0 a server admin must be defined in the [admins] section before the node will start, and new databases are admin-only. Keep those defaults and build named users and roles on top of them.
  • Treat the Erlang cookie as a cluster root secret. The -setcookie value in etc/vm.args is the password nodes use to join each other. Generate a long random value, store it like a credential and keep ports 4369 and 9100-9200 on a private network.
  • Bind narrowly and put TLS in front. Set [chttpd] bind_address to a private or loopback interface, enable the [ssl] section with tls_versions limited to TLS 1.2 or later, or terminate TLS at a reverse proxy.
  • Use _security objects for every database. Assign members and admins by role, avoid default_security = everyone, and turn on require_valid_user so anonymous requests are refused.
  • Replication documents hold credentials. Use the auth object with dedicated, least-privilege replication users, rotate them, and restrict who can read the _replicator database.

How identity and access work in Apache CouchDB

CouchDB has two layers of identity. Server admins live in the node configuration ([admins] in local.ini), are stored as salted PBKDF2 hashes (prefixed -pbkdf2-) and hold every privilege on the node. Users live as documents in the _users system database, with IDs of the form org.couchdb.user:<name>, a password that CouchDB hashes on write and a roles array that only admins can change. A user can never be given the _admin role through _users.

Authorisation for data is set per database through the _security object, which has two lists, each with names and roles:

LevelWhat it allowsHow it is set
Server adminEverything: create and delete databases, edit _security, design documents, _config, _compact, _purge, _active_tasks, node restart[admins] in local.ini or PUT /_node/_local/_config/admins/<name>
Database adminRead and write all documents including design documents, change membership and per-database settingsadmins list in PUT /{db}/_security
Database memberRead all documents and write non-design documentsmembers list in PUT /{db}/_security
_metrics roleRead only /_node/{node}/_stats and /_node/{node}/_systemRole in the user document (added in 3.0)
AnonymousOnly what a database's _security allows, plus /_up and /_sessionRefuse entirely with [chttpd] require_valid_user = true

Members can write documents but cannot change design documents, so finer rules (for example, a user may only edit their own documents) belong in a validate_doc_update function inside a design document, which only database admins can deploy.

Authentication methods

The [chttpd] authentication_handlers setting lists the methods the node accepts: cookie, default (HTTP Basic), proxy and jwt. Choose deliberately:

MethodUse it forKey settings
BasicService-to-service calls over TLSAlways pair with TLS, since credentials travel with every request; since 3.4 a successful Basic login also returns a session cookie
Cookie (POST /_session)Browser and interactive sessions[chttpd_auth] timeout (sessions last 10 minutes by default), secret, same_site (lax or strict), allow_persistent_cookies
TOTP two-factorHuman users who log in through /_sessionA per-user totp.key in the user document
ProxyAn SSO gateway that has already authenticated the userHeaders X-Auth-CouchDB-UserName, X-Auth-CouchDB-Roles, X-Auth-CouchDB-Token; set proxy_use_secret = true so the token is an HMAC with the shared secret
JWTTokens from your identity provider instead of _users accounts[jwt_keys] entries as <alg>:<kid> (HMAC, RSA or EC), [jwt_auth] required_claims such as exp,iat, roles_claim_path

Decision guidance: small teams with one application usually do well with Basic over TLS for the service plus cookie sessions for a few operators. Larger organisations should move human access to JWT or proxy authentication backed by the corporate identity provider, so joiners and leavers are handled centrally and MFA is enforced upstream. With JWT, CouchDB takes the username from the mandatory sub claim and rejects the none algorithm; every cluster node must carry the same key list. See the Database Credential and Access Security Guide for the wider pattern.

Admin roles and privileged access

Server admin is the most powerful identity in CouchDB, so keep the set small and named.

  • Bootstrap one admin, then name the rest: CouchDB needs one admin in [admins] to start. Use a long random password from your secrets manager at install time, then create named admin accounts for each operator through the config API and retire the generic bootstrap name.
  • Keep admin passwords out of plain-text files: CouchDB replaces a plain-text [admins] entry with its hash on startup. Make sure configuration management templates, container images and CI logs never keep the plain-text form after first boot.
  • Prefer database admins to server admins: most application owners need to deploy design documents and manage membership for their own databases, which the admins list in _security grants without node-wide power.
  • Use _metrics for monitoring: give scrapers and dashboards a user with only the _metrics role rather than admin credentials.
  • Tune password hashing: set [chttpd_auth] iterations and min_iterations to values your hardware can sustain, keep hash_algorithms on SHA-2 family values (the docs advise against md4 and md5), and leave upgrade_hash_on_auth on (the default since 3.5.0) so older hashes are upgraded at the next login.
  • Protect the _users database: keep users_db_public = false (the default) so only admins can browse user documents. If you need a public profile field, list it in public_fields rather than opening the whole document.

For broader controls over admin sessions, approvals and recording, see the Privileged Access Management Guide.

Integrations, API tokens and service accounts

Most CouchDB traffic comes from applications, sync clients and replication jobs, which makes these non-human identities the largest credential population on the node.

  • One user per application: create a _users account per service with a role named after it, and add that role to the members list of only the databases it needs. Never let applications run as a server admin.
  • Replication credentials: documents in _replicator carry source and target credentials. Use the auth object ("auth": {"basic": {"username": ..., "password": ...}}, available since 3.2.0) rather than user:pass@ in the URL, which the docs describe as deprecated under RFC 3986, or a base64 Authorization header, which the docs note can look encrypted when it is not. Give replication users member rights on the specific source and target databases only.
  • Control who runs replications: for non-admin users the replicator validation function requires user_ctx to carry their own name; only admins can run a replication on behalf of another user. Restrict write access to _replicator accordingly.
  • JWT for workloads: where your platform issues workload tokens, the jwt handler lets services authenticate with short-lived tokens and no stored password. Require exp in required_claims so tokens expire.
  • Rotation: change a user's password by updating its _users document with a new password field and the current _rev; rotate the cookie secret, proxy secret and JWT keys on a schedule and on staff changes. Store all of them in a secrets manager, not in application repositories. See the Secrets Management Guide.

Logging and detection

CouchDB writes its log through the [log] section. Set writer to file, syslog or journald and ship the output to your SIEM; for syslog the docs state that syslog_host is mandatory, alongside syslog_port and syslog_facility. Run at level = info or notice in production so requests and authentication outcomes are recorded without debug noise, and never set none.

SignalWhere to see itWhy it matters
Repeated 401 responses on /_session or any pathCouchDB request logPassword guessing against users or admins
PUT /_node/*/_config/*, especially adminsRequest logNew server admins or changed security settings
PUT /{db}/_securityRequest logMembership changes that widen access
New or changed design documentsRequest log, _changes feedValidation logic or views altered
New _replicator documents to unknown hosts_replicator changes, _scheduler/jobsData copied to an unexpected target
Connections to 4369 or 9100-9200 from non-cluster hostsFirewall or flow logsAttempts to reach Erlang distribution

Watch the HTTP interface from outside as well: an external scan that finds 5984, 6984, 4369 or the distribution range reachable from the internet is an incident to fix the same day. In MITRE ATT&CK terms these detections cover Exploit Public-Facing Application (T1190), Valid Accounts (T1078) and Unsecured Credentials (T1552) for replication passwords left in readable places. See the Database Audit Log Detection Guide.

Metrics that show the controls work:

  • Number of CouchDB endpoints reachable from the internet (target: zero).
  • Percentage of databases whose _security object names explicit roles (target: 100%).
  • Number of server admins, and the share that are named individuals rather than shared accounts.
  • Age of the oldest replication and service credential against your rotation policy.
  • Percentage of nodes on a supported release with the latest security update applied.

Hardening baseline

Network binding and ports

PortPurposeRecommended exposure
5984/tcpHTTP API ([chttpd] port)Loopback for a single node behind a local proxy; private interface for clusters; reach it from users only through TLS
6984/tcpHTTPS, as used in the docs' TLS exampleThe application network, never the open internet without an authenticating gateway
4369/tcpErlang port mapper (epmd)Loopback on a single node; private cluster interface only when clustered
9100-9200/tcpErlang inter-node distribution, pinned with inet_dist_listen_min and inet_dist_listen_max in vm.argsPrivate cluster interface, allowed only between cluster members

The cluster documentation is explicit that if the distribution port is reachable from untrusted networks, the Erlang cookie is the only protection. A peer holding the cookie can control the node completely, so treat cookie and network as a pair: a strong random -setcookie value shared only by cluster nodes, and firewall rules that limit 4369 and 9100-9200 to those nodes. Set -name couchdb@<fqdn> so node identity follows DNS, and rotate the cookie across the whole cluster in a planned window if it may have been exposed.

Baseline settings

  • Authentication required: [chttpd] require_valid_user = true (default false). Use require_valid_user_except_for_up = true if a load balancer needs anonymous health checks on /_up.
  • Database defaults: keep new databases admin-only; do not set [couchdb] default_security = everyone; keep admin_only_all_dbs = true (the default since 3.0) so database names are not listed to ordinary users.
  • TLS: in [ssl] set enable = true, cert_file, key_file, cacert_file, tls_versions = ['tlsv1.2'] or newer, and a reviewed ciphers list; set verify_ssl_certificates and fail_if_no_peer_cert to true where you want client certificates. If a reverse proxy terminates TLS, bind CouchDB to loopback and configure x_forwarded_proto handling. See the Database and Storage Encryption Guide.
  • Cookies: set [chttpd_auth] same_site = strict or lax, a short timeout for admin sessions and a unique secret shared by all nodes.
  • CORS: leave enable_cors = false unless a browser app needs it; then list exact origins (the docs note * cannot be combined with credentials = true).
  • Information and limits: set server_header_versions = false to drop version details from the Server header, set max_http_request_size to what your largest document needs, and enable enable_xframe_options for Fauxton.
  • Updates: run a supported release and apply security updates promptly; the project publishes fixes for the current and previous release series and lists advisories on its security issues page.

Phased rollout

  1. Inventory: list every CouchDB node, its version, bind_address, open ports and the _security object of each database (GET /{db}/_security as admin).
  2. Network first: restrict 4369 and 9100-9200 to cluster peers and remove any internet route to 5984 or 6984. This is the change with the largest risk reduction and the least application impact.
  3. Identities: create per-application users and roles, add them to _security, move replication documents to the auth object and replace shared admin use.
  4. Pilot require_valid_user: enable it on a staging node, run the application test suite and confirm health checks still pass, then enable it node by node in production.
  5. TLS and cookie hardening: enable [ssl] or the proxy, set cookie attributes, then rotate the Erlang cookie and cookie secret.
  6. Roll back safely: every setting above can be reverted through _config or local.ini; keep the prior values in version control and change one setting at a time so a failing client points to a single cause.

Framework mapping

Control areaNIST SP 800-53 Rev 5NIST CSF 2.0CIS Controls v8.1ISO/IEC 27001:2022
Bind, firewall, Erlang portsSC-7, CM-7PR.PS-014 (Secure Configuration), 12 (Network Infrastructure)A.8.20 Networks security
Admins, users, _security rolesAC-6, IA-2PR.AA-055 (Account Management), 6 (Access Control Management)A.5.15 Access control, A.8.2 Privileged access rights
Passwords, cookie, Erlang cookie, JWT keysIA-5PR.AA-055, 6A.5.17 Authentication information
TLSSC-8PR.DS-023 (Data Protection)A.8.24 Use of cryptography
Logging and monitoringAU-2DE.CM-018 (Audit Log Management)A.8.15 Logging, A.8.16 Monitoring activities

Common misconfigurations

  • Binding to 0.0.0.0 on a public host: the cluster setup example uses 0.0.0.0 for reachability inside a private network. Copying it to an internet-facing host without a firewall publishes the API. Bind to the private interface and filter at the network edge.
  • Reusing the example Erlang cookie: sample values from documentation or container images end up in production. Generate a unique random cookie per cluster and keep the distribution ports private.
  • Opening databases with default_security = everyone: this treats anonymous and ordinary users as members of every new database. Leave the admin-only default and grant roles explicitly.
  • Applications running as server admin: a leaked application password then grants _config access. Give each application a member role on its own databases.
  • Credentials in replication URLs: user:pass@host strings are copied into tickets and scripts. Use the auth object with a dedicated replication user and rotate it.
  • Basic authentication without TLS: credentials cross the network in every request. Enable [ssl] or terminate TLS at a proxy before allowing remote clients.

Practitioner checklist

  • Confirm every node runs CouchDB 3.x or later on a supported release with current security updates.
  • Bind 5984 to loopback or a private interface and confirm no internet route to 5984 or 6984.
  • Restrict 4369 and 9100-9200 to cluster peers and replace any example Erlang cookie with a unique random value.
  • Replace the bootstrap admin with named server admins and keep the count small.
  • Set require_valid_user = true and keep new databases admin-only.
  • Give every database a _security object with role-based members and admins.
  • Create one user per application and per replication job, with no server admin rights.
  • Move replication credentials into the auth object and store all secrets in a secrets manager.
  • Enable TLS 1.2 or later and set same_site and timeout for session cookies.
  • Ship [log] output to the SIEM and alert on _config, _security and replication changes.

Standards and references

Related NHI Mgmt Group resources: Database Security Guide · Database Credential and Access Security Guide · Database Audit Log Detection Guide · Secrets Management Guide

Free weekly newsletter

Subscribe to the NHI & AI Identity Journal

The latest on NHI and Agentic AI security – articles, research, breaches, news and events every week.

Bonus 33% off our NHI Course when you subscribe.

NHIMG Editorial Note
Researched and written by the NHI Mgmt Group editorial team using AI tools, under the editorial direction of Lalit Choda. Facts are drawn from the sources listed on this page and checked by our automated quality process. Last updated 8 November 2026. Spotted an error? Use our contact page.
NHI Mgmt Group, the independent authority on Non-Human Identity, IAM and Agentic AI security. nhimg.org