4.6. Reverse Proxies

4.6.1. Reverse proxying with HAProxy

CouchDB recommends the use of HAProxy as a load balancer and reverse proxy. The team’s experience with using it in production has shown it to be superior for configuration and monitoring capabilities, as well as overall performance.

CouchDB’s sample haproxy configuration is present in the code repository and release tarball as rel/haproxy.cfg. It is included below. This example is for a 3 node CouchDB cluster:

  1. global
  2. maxconn 512
  3. spread-checks 5
  4. defaults
  5. mode http
  6. log global
  7. monitor-uri /_haproxy_health_check
  8. option log-health-checks
  9. option httplog
  10. balance roundrobin
  11. option forwardfor
  12. option redispatch
  13. retries 4
  14. option http-server-close
  15. timeout client 150000
  16. timeout server 3600000
  17. timeout connect 500
  18. stats enable
  19. stats uri /_haproxy_stats
  20. # stats auth admin:admin # Uncomment for basic auth
  21. frontend http-in
  22. # This requires HAProxy 1.5.x
  23. # bind *:$HAPROXY_PORT
  24. bind *:5984
  25. default_backend couchdbs
  26. backend couchdbs
  27. option httpchk GET /_up
  28. http-check disable-on-404
  29. server couchdb1 x.x.x.x:5984 check inter 5s
  30. server couchdb2 x.x.x.x:5984 check inter 5s
  31. server couchdb2 x.x.x.x:5984 check inter 5s

4.6.2. Reverse proxying with nginx

4.6.2.1. Basic Configuration

Here’s a basic excerpt from an nginx config file in <nginx config directory>/sites-available/default. This will proxy all requests from http://domain.com/... to http://localhost:5984/...

  1. location / {
  2. proxy_pass http://localhost:5984;
  3. proxy_redirect off;
  4. proxy_buffering off;
  5. proxy_set_header Host $host;
  6. proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  7. }

Proxy buffering must be disabled, or continuous replication will not function correctly behind nginx.

4.6.2.2. Reverse proxying CouchDB in a subdirectory with nginx

It can be useful to provide CouchDB as a subdirectory of your overall domain, especially to avoid CORS concerns. Here’s an excerpt of a basic nginx configuration that proxies the URL http://domain.com/couchdb to http://localhost:5984 so that requests appended to the subdirectory, such as http://domain.com/couchdb/db1/doc1 are proxied to http://localhost:5984/db1/doc1.

  1. location /couchdb {
  2. rewrite /couchdb/(.*) /$1 break;
  3. proxy_pass http://localhost:5984;
  4. proxy_redirect off;
  5. proxy_buffering off;
  6. proxy_set_header Host $host;
  7. proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  8. }

Session based replication is default functionality since CouchDB 2.3.0. To enable session based replication with reverse proxied CouchDB in a subdirectory.

  1. location /_session {
  2. proxy_pass http://localhost:5984/_session;
  3. proxy_redirect off;
  4. proxy_buffering off;
  5. proxy_set_header Host $host;
  6. proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  7. }

4.6.2.3. Authentication with nginx as a reverse proxy

Here’s a sample config setting with basic authentication enabled, placing CouchDB in the /couchdb subdirectory:

  1. location /couchdb {
  2. auth_basic "Restricted";
  3. auth_basic_user_file htpasswd;
  4. rewrite /couchdb/(.*) /$1 break;
  5. proxy_pass http://localhost:5984;
  6. proxy_redirect off;
  7. proxy_buffering off;
  8. proxy_set_header Host $host;
  9. proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  10. proxy_set_header Authorization "";
  11. }

This setup leans entirely on nginx performing authorization, and forwarding requests to CouchDB with no authentication (with CouchDB in Admin Party mode), which isn’t sufficient in CouchDB 3.0 anymore as Admin Party has been removed. You’d need to at the very least hard-code user credentials into this version with headers.

For a better solution, see Proxy Authentication.

4.6.2.4. SSL with nginx

In order to enable SSL, just enable the nginx SSL module, and add another proxy header:

  1. ssl on;
  2. ssl_certificate PATH_TO_YOUR_PUBLIC_KEY.pem;
  3. ssl_certificate_key PATH_TO_YOUR_PRIVATE_KEY.key;
  4. ssl_protocols SSLv3;
  5. ssl_session_cache shared:SSL:1m;
  6. location / {
  7. proxy_pass http://localhost:5984;
  8. proxy_redirect off;
  9. proxy_set_header Host $host;
  10. proxy_buffering off;
  11. proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  12. proxy_set_header X-Forwarded-Ssl on;
  13. }

The X-Forwarded-Ssl header tells CouchDB that it should use the https scheme instead of the http scheme. Otherwise, all CouchDB-generated redirects will fail.

4.6.3. Reverse Proxying with Caddy 2

Caddy is https-by-default, and will automatically acquire, install, activate and, when necessary, renew a trusted SSL certificate for you - all in the background. Certificates are issued by the Let’s Encrypt certificate authority.

4.6.3.1. Basic configuration

Here’s a basic excerpt from a Caddyfile in /etc/caddy/Caddyfile. This will proxy all requests from http(s)://domain.com/... to http://localhost:5984/...

  1. domain.com {
  2. reverse_proxy localhost:5984
  3. }

4.6.3.2. Reverse proxying CouchDB in a subdirectory with Caddy 2

It can be useful to provide CouchDB as a subdirectory of your overall domain, especially to avoid CORS concerns. Here’s an excerpt of a basic Caddy configuration that proxies the URL http(s)://domain.com/couchdb to http://localhost:5984 so that requests appended to the subdirectory, such as http(s)://domain.com/couchdb/db1/doc1 are proxied to http://localhost:5984/db1/doc1.

  1. domain.com {
  2. reverse_proxy /couchdb/* localhost:5984
  3. }

4.6.3.3. Reverse proxying + load balancing for CouchDB clusters

Here’s a basic excerpt from a Caddyfile in /<path>/<to>/<site>/Caddyfile. This will proxy and evenly distribute all requests from http(s)://domain.com/... among 3 CouchDB cluster nodes at localhost:15984, localhost:25984 and localhost:35984.

Caddy will check the status, i.e. health, of each node every 5 seconds; if a node goes down, Caddy will avoid proxying requests to that node until it comes back online.

  1. domain.com {
  2. reverse_proxy http://localhost:15984 http://localhost:25984 http://localhost:35984 {
  3. lb_policy round_robin
  4. lb_try_interval 500ms
  5. health_interval 5s
  6. }
  7. }

4.6.3.4. Authentication with Caddy 2 as a reverse proxy

Here’s a sample config setting with basic authentication enabled, placing CouchDB in the /couchdb subdirectory:

  1. domain.com {
  2. basicauth /couchdb/* {
  3. couch_username couchdb_hashed_password_base64
  4. }
  5. reverse_proxy /couchdb/* localhost:5984
  6. }

This setup leans entirely on nginx performing authorization, and forwarding requests to CouchDB with no authentication (with CouchDB in Admin Party mode), which isn’t sufficient in CouchDB 3.0 anymore as Admin Party has been removed. You’d need to at the very least hard-code user credentials into this version with headers.

For a better solution, see Proxy Authentication.

4.6.4. Reverse Proxying with Apache HTTP Server

4.6.4.1. Basic Configuration

Here’s a basic excerpt for using a VirtualHost block config to use Apache as a reverse proxy for CouchDB. You need at least to configure Apache with the --enable-proxy --enable-proxy-http options and use a version equal to or higher than Apache 2.2.7 in order to use the nocanon option in the ProxyPass directive. The ProxyPass directive adds the X-Forwarded-For header needed by CouchDB, and the ProxyPreserveHost directive ensures the original client Host header is preserved.

  1. <VirtualHost *:80>
  2. ServerAdmin webmaster@dummy-host.example.com
  3. DocumentRoot "/opt/websites/web/www/dummy"
  4. ServerName couchdb.localhost
  5. AllowEncodedSlashes On
  6. ProxyRequests Off
  7. KeepAlive Off
  8. <Proxy *>
  9. Order deny,allow
  10. Deny from all
  11. Allow from 127.0.0.1
  12. </Proxy>
  13. ProxyPass / http://localhost:5984 nocanon
  14. ProxyPassReverse / http://localhost:5984
  15. ProxyPreserveHost On
  16. ErrorLog "logs/couchdb.localhost-error_log"
  17. CustomLog "logs/couchdb.localhost-access_log" common
  18. </VirtualHost>