Apache CouchDB on AWS User Guide
Overview
This image runs Apache CouchDB, the open source document oriented NoSQL database, on a single node. CouchDB stores data as JSON documents, exposes every operation over a RESTful HTTP API, and ships with the Fauxton browser based admin interface. The Erlang virtual machine that CouchDB runs on is bundled inside the CouchDB package, so the image carries no separate runtime dependency and no Java.
The HTTP REST API, the Fauxton admin interface, and the replication protocol all listen on a single port, 5984. This is the simplest network exposure surface of any database image in the cloudimg catalogue, and it is also the single most important security consideration, because opening port 5984 to the public internet exposes the Fauxton admin interface as well as the data plane. The security section of this guide covers the posture you want before putting application traffic through the server.
The CouchDB administrator password is generated on the first boot of every deployed instance. Two instances launched from the same Amazon Machine Image never share a password. Without an administrator account CouchDB would run in insecure admin party mode, so the image generates a fresh administrator password on first boot, writes it into the CouchDB configuration, and stores the plain text value in /root/couchdb-credentials.txt with mode 0600 so that only the root user can read it.
CouchDB's database files are kept on a dedicated EBS data volume mounted at /var/lib/couchdb, separate from the operating system disk, so the data tier can be resized independently of the root volume.
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 allowing inbound port 22 from your management network and inbound port 5984 from the trusted networks that host the applications which will talk to CouchDB
- The AWS CLI (version 2) installed locally if you plan to deploy from the command line
Step 1: Launch the Instance from the AWS Marketplace
Sign in to the AWS Management Console, open the EC2 service, and select Launch instance. Under Application and OS Images choose AWS Marketplace AMIs and search for Apache CouchDB. Select the cloudimg listing and choose Select, then Continue on the subscription summary.
Pick an instance type of m5.large or larger. Choose your EC2 key pair under Key pair (login). Under Network settings select your VPC and subnet, and either create or select a security group that allows inbound port 22 from your management network and inbound port 5984 from the trusted networks that will reach CouchDB. Do not open port 5984 to the public internet, because the Fauxton admin interface is served on that port. Leave the root volume at the default size or larger.
Select Launch instance. First boot initialisation takes approximately one minute after the instance state becomes Running and the status checks pass.
Step 2: Launch the Instance from the AWS CLI
The following block launches an instance from the cloudimg Apache CouchDB Marketplace AMI into an existing subnet and security group. Replace <ami-id> with the AMI ID shown on the Marketplace listing, <key-name> with your EC2 key pair name, <subnet-id> with your subnet ID, and <security-group-id> with a security group that opens ports 22 and 5984 as described above.
aws ec2 run-instances \
--image-id <ami-id> \
--instance-type m5.large \
--key-name <key-name> \
--subnet-id <subnet-id> \
--security-group-ids <security-group-id> \
--block-device-mappings '[{"DeviceName":"/dev/sda1","Ebs":{"VolumeSize":30,"VolumeType":"gp3"}}]' \
--tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=couchdb-01}]'
The command prints a JSON document on success. Note the instance ID, then retrieve its public address once it is running with aws ec2 describe-instances --instance-ids <instance-id> --query "Reservations[].Instances[].PublicIpAddress" --output text.
Step 3: Connect and Retrieve the Administrator Password
Connect over SSH with the key pair you selected and the public IP address from step 2. The SSH login user depends on the operating system of the AMI variant you launched:
| AMI variant | SSH login user |
|---|---|
| Apache CouchDB 3 on Ubuntu 24.04 | ubuntu |
The first boot service runs before the SSH daemon becomes ready, so the credentials file is always in place when you log in for the first time.
ssh <login-user>@<public-ip>
sudo cat /root/couchdb-credentials.txt
You will see a plain text file containing the CouchDB URL, the Fauxton URL, the administrator username (admin), and the administrator password. Copy these values somewhere secure such as a password manager or an encrypted vault, and do not commit them to source control.
Each command block in this guide that talks to CouchDB begins by reading the administrator password from the credentials file into a PASSWORD shell variable, so every block is self contained:
PASSWORD="$(sudo awk -F= '/^couchdb.admin.pass=/ {print $2}' /root/couchdb-credentials.txt)"
echo "admin password length: ${#PASSWORD}"
Step 4: Verify the Server is Healthy
CouchDB has two endpoints that confirm the server is running. The welcome endpoint at / returns a JSON document reporting the installed version, and /_up is a dedicated health probe. Both require HTTP Basic authentication because the image ships with require_valid_user = true:
PASSWORD="$(sudo awk -F= '/^couchdb.admin.pass=/ {print $2}' /root/couchdb-credentials.txt)"
curl -s -u "admin:$PASSWORD" http://127.0.0.1:5984/
curl -s -u "admin:$PASSWORD" http://127.0.0.1:5984/_up
The welcome response reports "couchdb":"Welcome" and the installed CouchDB version:
{"couchdb":"Welcome","version":"3.5.2","git_sha":"5b4d92103","uuid":"d1b4451426aa835fc5889f0d97fbee73","features":["access-ready","partitioned","pluggable-storage-engines","reshard","scheduler"],"vendor":{"name":"The Apache Software Foundation"}}
The /_up response returns {"seeds":{},"status":"ok"}, which confirms the server is ready to accept requests.
Step 5: Server Components
| Component | Version | Source |
|---|---|---|
| Apache CouchDB | 3.5.x | apache.jfrog.io/artifactory/couchdb-deb |
| Erlang VM | bundled in the CouchDB package | Apache CouchDB package |
| Ubuntu | 24.04 LTS | cloudimg golden base image |
| cloudimg overrides | 20-cloudimg.ini |
baked into the image |
CouchDB ships the Erlang virtual machine statically bundled under /opt/couchdb, so the image has no system Erlang dependency and there is no Java runtime on the image. There is no separate backend database, no message broker, and no second port, so there is nothing else to lifecycle.
Step 6: Filesystem Layout
CouchDB is self contained under /opt/couchdb, and its database files live on a dedicated EBS volume mounted at /var/lib/couchdb. The main directories and files the image exposes are:
/opt/couchdb/bin/couchdb— the CouchDB launcher script/opt/couchdb/etc/local.ini— primary configuration file, defaults shipped with the package/opt/couchdb/etc/local.d/20-cloudimg.ini— cloudimg overrides (port, bind address, auth mode, data directory)/opt/couchdb/etc/local.d/90-admins.ini— admin credentials (plaintext at first boot, hashed by CouchDB after daemon startup)/var/lib/couchdb/— all database files and the cluster metadata, on the dedicated data volume/opt/couchdb/var/log/couchdb.log— structured log output/root/couchdb-credentials.txt— per instance administrator password, mode 0600 root only
Step 7: Start, Stop, and Check Status
CouchDB runs as the systemd service couchdb.service. The first boot unit is couchdb-firstboot.service and is skipped on every boot after the first because its sentinel lives at /var/lib/cloudimg/couchdb-firstboot.done. You interact with the main service using systemctl:
sudo systemctl status --no-pager couchdb
sudo systemctl is-active couchdb
To restart the server after editing configuration:
sudo systemctl restart couchdb
The service runs as the couchdb system user, owns /opt/couchdb and /var/lib/couchdb, and writes its logs to /opt/couchdb/var/log/couchdb.log.
Step 8: Open the Fauxton Admin Interface
CouchDB ships with Fauxton, a browser based admin interface that runs on the same port as the REST API, 5984. Once you have opened port 5984 from your management network in the security group, open the following URL in your browser:
http://<public-ip>:5984/_utils/
Fauxton presents a sign in page. Enter the administrator username admin and the administrator password from /root/couchdb-credentials.txt.

After you sign in, Fauxton shows the all databases overview. A freshly launched instance has no user databases yet, so the list is empty until you create one. The left hand navigation gives you database browsing, document editing, the Mango query builder, the replication control panel, and the server configuration page.

Because Fauxton speaks the same REST API as every other client, anything you can do in Fauxton you can also do with curl, and vice versa.
Step 9: Create a Database and a Document
Every CouchDB write is an HTTP request. Create a database with PUT, write a JSON document with POST, and list documents with GET:
PASSWORD="$(sudo awk -F= '/^couchdb.admin.pass=/ {print $2}' /root/couchdb-credentials.txt)"
curl -s -u "admin:$PASSWORD" -X PUT http://127.0.0.1:5984/catalog
curl -s -u "admin:$PASSWORD" -X POST http://127.0.0.1:5984/catalog \
-H 'Content-Type: application/json' \
-d '{"type":"book","title":"CouchDB The Definitive Guide","year":2010}'
curl -s -u "admin:$PASSWORD" "http://127.0.0.1:5984/catalog/_all_docs?include_docs=true"
The first call returns {"ok":true}. The second returns {"ok":true,"id":"<generated-uuid>","rev":"1-<hash>"}. The third returns a JSON document that lists every document in the database with its _id, _rev, and, because of include_docs=true, the document body. In Fauxton the same database and its documents are visible by selecting the database name and then a document row.

Step 10: Query with Mango
Mango is CouchDB's declarative query language. It uses a JSON selector syntax and returns results from the /_find endpoint. Without an explicit index Mango falls back to a full scan and CouchDB prints a warning, which is fine for ad hoc queries over small databases:
PASSWORD="$(sudo awk -F= '/^couchdb.admin.pass=/ {print $2}' /root/couchdb-credentials.txt)"
curl -s -u "admin:$PASSWORD" -X POST http://127.0.0.1:5984/catalog/_find \
-H 'Content-Type: application/json' \
-d '{"selector":{"type":"book"}}'
The response contains a docs array with every document matching the selector. For production use, create an index with POST /<db>/_index so Mango can plan against it instead of scanning every document.
Step 11: Create Per Application Users
The administrator account should never be used by application traffic. Create a per application user by writing a user document into the built in _users database, then grant the user read or write access to a database by PUTting _security on the target database:
PASSWORD="$(sudo awk -F= '/^couchdb.admin.pass=/ {print $2}' /root/couchdb-credentials.txt)"
curl -s -u "admin:$PASSWORD" -X PUT http://127.0.0.1:5984/_users/org.couchdb.user:app1 \
-H 'Content-Type: application/json' \
-d '{"name":"app1","password":"change-me-in-your-secrets-manager","roles":[],"type":"user"}'
curl -s -u "admin:$PASSWORD" -X PUT http://127.0.0.1:5984/catalog/_security \
-H 'Content-Type: application/json' \
-d '{"admins":{"names":[],"roles":[]},"members":{"names":["app1"],"roles":[]}}'
From the application side, connect using HTTP Basic auth exactly as the administrator does, just with the new credentials. CouchDB hashes the stored password on daemon restart, so the plain text in the PUT body above is not persisted.
Step 12: Rotate the Administrator Password
For a production deployment, rotate the administrator password that was generated on first boot. PUT the new value to the admin config endpoint. CouchDB hashes it on the next config read. After the rotation, update /root/couchdb-credentials.txt so future readers see the current value.
PASSWORD="$(sudo awk -F= '/^couchdb.admin.pass=/ {print $2}' /root/couchdb-credentials.txt)"
NEW_PASSWORD="$(head -c 32 /dev/urandom | base64 | tr -d '/+=' | head -c 24)"
curl -s -u "admin:$PASSWORD" -X PUT \
http://127.0.0.1:5984/_node/_local/_config/admins/admin \
-H 'Content-Type: application/json' \
--data "\"$NEW_PASSWORD\""
sudo sed -i "s|^couchdb.admin.pass=.*|couchdb.admin.pass=$NEW_PASSWORD|" /root/couchdb-credentials.txt
export PASSWORD="$NEW_PASSWORD"
Store the new value in your secrets manager immediately. The file /root/couchdb-credentials.txt should not be considered your source of truth after first boot.
Step 13: Configure Replication
CouchDB replicates by writing a document to the _replicator database that describes the source, target, and policy. A pull replication from a remote peer into a local database looks like this:
PASSWORD="$(sudo awk -F= '/^couchdb.admin.pass=/ {print $2}' /root/couchdb-credentials.txt)"
curl -s -u "admin:$PASSWORD" -X POST http://127.0.0.1:5984/_replicator \
-H 'Content-Type: application/json' \
-d '{"_id":"pull-from-peer","source":"http://remote.example.com:5984/catalog","target":"http://admin:local@127.0.0.1:5984/catalog","continuous":true}'
Replace the source URL with your peer and substitute peer credentials as needed. Replication state is visible in Fauxton under Replication, or with GET /_scheduler/docs.
Step 14: Enable HTTPS with a Reverse Proxy
CouchDB serves the REST API and the Fauxton admin interface over plain HTTP on port 5984. For any deployment that carries customer traffic, terminate TLS with a reverse proxy in front of CouchDB so credentials and data are not sent in clear text. nginx with a Let's Encrypt certificate gives you HTTPS without changing the CouchDB configuration.
The following assumes you have a DNS record pointing your fully qualified domain name at the instance's public IP address.
sudo apt-get update && sudo apt-get install -y nginx certbot python3-certbot-nginx
Create an nginx server block that proxies to http://127.0.0.1:5984, then obtain a certificate:
sudo certbot --nginx -d couchdb.your-domain.example \
--non-interactive --agree-tos -m you@your-domain.example \
--redirect
Customer applications then talk to https://couchdb.your-domain.example, and the proxy speaks to CouchDB on localhost. Restrict port 5984 in the security group to the loopback or the instance itself once the proxy is in place.
Step 15: Backups and Maintenance
CouchDB keeps all of its data under /var/lib/couchdb on the dedicated data volume. CouchDB's append only file format tolerates a tarball snapshot of a running database, but for a point in time consistent backup, stop the service, snapshot the EBS volume, and start the service again:
sudo systemctl stop couchdb
sudo tar -czf /var/backups/couchdb-data-$(date +%F).tgz -C /var/lib/couchdb .
sudo systemctl start couchdb
Ship the archive to an Amazon S3 bucket or another object store. For larger databases, take an Amazon EBS snapshot of the /var/lib/couchdb volume instead, which is faster and does not need a service stop if your workload tolerates a crash consistent snapshot.
For kernel and package updates, Ubuntu's unattended-upgrades is enabled by default, so security patches apply automatically. To update CouchDB itself, use sudo apt-get update && sudo apt-get install --only-upgrade couchdb and then restart the service.
Step 16: Scaling Beyond a Single Instance
This image is a single node CouchDB. For larger deployments:
- Grow the
/var/lib/couchdbEBS volume and extend the filesystem when the database outgrows the initial disk - Move to a multi node CouchDB cluster for horizontal scale and high availability, replicating across three or more nodes
- Put the CouchDB tier behind an Application Load Balancer with TLS termination, with the security group restricting port 5984 to the load balancer and the application subnets
- Use CouchDB's native replication to keep a warm standby in a second Availability Zone or Region
The official CouchDB documentation at https://docs.couchdb.org covers cluster setup, sharding, and the replication protocol in detail.
Step 17: Security Recommendations
CouchDB serves the REST API, the Fauxton admin interface, and the replication protocol all on port 5984. The single port model means the security posture of that port matters more than for most databases. Before taking customer traffic, apply the following:
- Never expose port 5984 to the public internet. The Fauxton admin interface is on that port. Restrict the security group rule to your application subnets and management network.
- Rotate the administrator password using the rotation step above and store the new value in your secrets manager.
- Create a per application user and stop using the administrator account for application traffic. Only administrative operations should use the administrator credential.
- Terminate TLS with a reverse proxy so credentials and data are encrypted in transit.
- Keep CORS disabled unless you serve Fauxton to browsers from another origin.
enable_cors = falseis the cloudimg default and is correct for server to server traffic. - Back up
/var/lib/couchdbregularly and test restores.
Support
cloudimg provides 24/7/365 expert technical support for this image. Guaranteed response within 24 hours, one hour average for critical issues. Contact support@cloudimg.co.uk.
For general Apache CouchDB questions, tuning, and the replication protocol, consult the official documentation at https://docs.couchdb.org and the Apache CouchDB community at https://couchdb.apache.org.