How to Set Up Nginx as a Reverse Proxy for Couchbase

How to Set Up Nginx as a Reverse Proxy for Couchbase

Couchbase is a distributed NoSQL database, and unlike a typical single-port web application, it spreads its functionality across a whole range of ports: the web admin console, the REST management API, the Data (KV) service, Query (N1QL), Search (FTS), Analytics, and Views, each with its own port and often its own TLS-enabled variant. That spread is exactly why reverse proxying Couchbase needs a more deliberate approach than a single proxy_pass block — deciding what gets proxied, and how, depends entirely on which services actually need external access.

This guide covers setting up Nginx in front of Couchbase’s web console and REST/query APIs, and explains why proxying the Data service works differently from the rest.

Understanding Couchbase’s Port Layout

Before writing any Nginx configuration, it helps to know what’s actually running where. A default Couchbase Server node exposes (non-TLS ports shown; TLS equivalents typically add 1 to the ten-thousands digit or a fixed offset depending on version — always confirm exact ports against the running cluster’s admin console):

  • 8091 — Web Console / Cluster Manager REST API (HTTP)
  • 18091 — Web Console / Cluster Manager REST API (HTTPS)
  • 8092 — Views (HTTP)
  • 18092 — Views (HTTPS)
  • 8093 — Query service / N1QL (HTTP)
  • 18093 — Query service / N1QL (HTTPS)
  • 8094 — Search service / FTS (HTTP)
  • 18094 — Search service / FTS (HTTPS)
  • 8095 — Analytics service (HTTP)
  • 18095 — Analytics service (HTTPS)
  • 11210 / 11207 — Data service (KV), binary Couchbase protocol, not HTTP

That last one is the key distinction: the Data service, which is what SDKs actually use for the bulk of read/write operations, speaks a binary protocol over 11210/11207, not HTTP. It cannot be proxied with Nginx’s standard http module the same way the console and query APIs can — it would need the stream module for raw TCP forwarding, similar to how Redis is handled, and even then, Couchbase SDKs perform their own internal node discovery and connection management that doesn’t play well with a simple TCP proxy in front of it. For that reason, most real-world Couchbase reverse proxy setups focus on the HTTP-based services — the web console, REST management API, Query, Search, and Analytics — and leave direct SDK/Data-service traffic on the private network, unproxied.

Requirements

  • A running Couchbase Server cluster, reachable internally on its standard ports.
  • Nginx installed on a front-end host.
  • A domain name pointing at the Nginx server.
  • A TLS certificate for that domain.
  • Awareness of which Couchbase services actually need external exposure — for most setups, this is just the web console and the Query service.

Install Nginx:

sudo apt update && sudo apt install nginx -y

Confirm Couchbase’s web console is reachable:

curl -u Administrator:password http://127.0.0.1:8091/pools/default

Step 1: Decide What to Expose

A reasonable default policy:

  • Web Console (8091) — proxy it, but restrict access tightly (IP allowlist plus authentication), since it allows full cluster administration.
  • Query service (8093) — proxy it for applications that query Couchbase over HTTP/N1QL from outside the private network, with its own access controls.
  • Data service (11210) — do not proxy through Nginx; keep SDK traffic on the private network or behind a dedicated TCP load balancer designed for Couchbase SDK connection patterns.
  • Views, Search, Analytics — proxy only if actively used and only to the extent needed, following the same restrictive pattern as the Query service.

Step 2: Write the Nginx Configuration

Create the config file:

sudo nano /etc/nginx/sites-available/couchbase.conf

Example configuration proxying the web console and Query service, each under its own subdomain:

# Web Console / Cluster Manager
server {
    listen 80;
    server_name couchbase-admin.example.com;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;
    server_name couchbase-admin.example.com;

    ssl_certificate     /etc/letsencrypt/live/couchbase-admin.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/couchbase-admin.example.com/privkey.pem;
    ssl_protocols       TLSv1.2 TLSv1.3;
    ssl_ciphers         HIGH:!aNULL:!MD5;

    # Restrict to known internal/admin IP ranges
    allow 10.0.0.0/8;
    allow 203.0.113.10;
    deny all;

    location / {
        proxy_pass http://127.0.0.1:8091;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

        # The console UI uses long-polling for some cluster status views
        proxy_read_timeout 120s;
        proxy_send_timeout 120s;

        proxy_http_version 1.1;
        proxy_set_header Connection "";
    }
}

# Query (N1QL) service
server {
    listen 443 ssl;
    server_name couchbase-query.example.com;

    ssl_certificate     /etc/letsencrypt/live/couchbase-query.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/couchbase-query.example.com/privkey.pem;
    ssl_protocols       TLSv1.2 TLSv1.3;

    location / {
        auth_basic "Couchbase Query API";
        auth_basic_user_file /etc/nginx/.couchbase_htpasswd;

        proxy_pass http://127.0.0.1:8093;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

        proxy_read_timeout 60s;
        proxy_send_timeout 60s;
    }
}

Generate the htpasswd file for the query endpoint if that layer of access control is desired in addition to Couchbase’s own RBAC:

sudo apt install apache2-utils -y
sudo htpasswd -c /etc/nginx/.couchbase_htpasswd query_user

Enable and test:

sudo ln -s /etc/nginx/sites-available/couchbase.conf /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx

Step 3: Testing the Setup

Test the console through the proxy (from an allowed IP):

curl -Ik https://couchbase-admin.example.com/

Log into the web console in a browser and confirm the cluster overview, bucket list, and node status pages all load correctly, since some of these views poll the REST API repeatedly and will surface any proxy timeout issues quickly.

Test the Query service:

curl -u query_user -k https://couchbase-query.example.com/query/service \
  -d 'statement=SELECT COUNT(*) FROM `travel-sample`'

A valid JSON response with query results confirms the Query service proxy is working end to end, including the basic auth layer and the underlying Couchbase RBAC check.

Troubleshooting

502 Bad Gateway on the console Confirm Couchbase is actually running and the web console is bound to the expected port:

sudo systemctl status couchbase-server
sudo ss -tlnp | grep 8091

Console loads but cluster status doesn’t update / pages hang The web console relies on repeated REST polling and occasionally long-held connections for certain views. Increase proxy_read_timeout and confirm proxy_http_version 1.1 with proxy_set_header Connection ""; is set, which allows keepalive connections to the backend rather than forcing a new connection per poll.

Query requests return 401 despite correct Couchbase credentials This usually means the Nginx auth_basic layer is being confused with Couchbase’s own authentication — these are two separate credential sets. The Nginx-level basic auth (query_user) gates access to the proxy itself; the actual N1QL query still needs to authenticate against Couchbase separately, either via the Authorization header passed through to Couchbase, or by including credentials in the query request as the Couchbase client library expects.

SDK connections fail when pointed at the proxy This is expected if the Data service (11210) traffic is being routed at an HTTP proxy — it won’t work, since that’s a binary protocol, not HTTP. Couchbase SDKs also perform cluster topology discovery that assumes direct node connectivity; pointing an SDK at an HTTP reverse proxy for anything beyond simple REST calls is not a supported pattern. Keep SDK connections on the private network.

Views or Analytics endpoints time out on large result sets Increase proxy_read_timeout for those specific service ports, and check proxy_buffer_size/proxy_buffers, since large aggregation or analytics results can exceed default buffer allocations.

Security Considerations

  • Treat the web console as a high-privilege administrative interface. IP-restrict it aggressively, and don’t rely on basic auth alone — Couchbase’s own role-based access control should also be configured with least-privilege accounts.
  • Never expose the Data service port (11210/11207) externally, proxied or not. It’s meant for private, trusted network access by SDKs and internal services only.
  • Use TLS everywhere, both at the Nginx layer and, ideally, between Nginx and Couchbase itself if they’re on different hosts, using Couchbase’s TLS-enabled ports (the 1 + standard port pattern).
  • Apply standard security headers to the web-facing services:
add_header X-Frame-Options SAMEORIGIN;
add_header X-Content-Type-Options nosniff;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
  • Rate limit the Query service if it’s exposed to any semi-trusted or public consumer, since N1QL queries can be resource-intensive and a flood of expensive queries can degrade cluster performance quickly:
limit_req_zone $binary_remote_addr zone=cb_query:10m rate=20r/s;

location / {
    limit_req zone=cb_query burst=40 nodelay;
    proxy_pass http://127.0.0.1:8093;
}
  • Audit which services are actually proxied periodically. It’s easy for a “just proxy everything” setup to accumulate exposed ports (Views, Analytics, Search) that aren’t actually in active use anymore but remain reachable.

Performance Tips

  • Enable keepalive connections to the Couchbase backend for the console and Query service, since both benefit from avoiding repeated TCP handshake overhead under regular polling or query load:
upstream couchbase_query {
    server 127.0.0.1:8093;
    keepalive 32;
}
  • Cache static console assets (JS/CSS bundles served by the web console) if they’re being requested repeatedly, though this offers limited benefit compared to the API endpoints themselves.
  • Load balance Query/Search/Analytics requests across multiple cluster nodes running those services, rather than pointing Nginx at a single node, to spread load evenly and avoid a single point of failure for those services:
upstream couchbase_query_nodes {
    least_conn;
    server 10.0.1.21:8093;
    server 10.0.1.22:8093;
    server 10.0.1.23:8093;
}
  • Set query timeouts thoughtfully. N1QL queries against large datasets can legitimately take longer than typical REST calls; tune proxy_read_timeout to match realistic query execution time rather than leaving default web-app-style short timeouts in place.

Real-World Use Cases

  • Exposing the Query (N1QL) API to external analytics tools or partner integrations without exposing the entire cluster’s administrative surface.
  • Providing secure, IP-restricted admin console access for a distributed ops team without requiring a full VPN for every console login.
  • Centralizing TLS certificate management across a multi-node Couchbase cluster, so certificate renewal happens once at the Nginx layer instead of being managed independently per node.
  • Gradual migration or multi-cluster setups, where Nginx routes different subdomains or paths to different Couchbase clusters during a migration window.

Best Practices Checklist

  • Only proxy the HTTP-based services (console, Query, Views, Search, Analytics) — never attempt to HTTP-proxy the binary Data service port.
  • Keep the Data service (11210/11207) on the private network only, reachable directly by SDKs, not through Nginx.
  • Aggressively restrict access to the web console by IP and authentication, since it’s a full administrative interface.
  • Layer Nginx-level access control (basic auth, IP allowlists) on top of, not instead of, Couchbase’s own RBAC.
  • Use keepalive connections and appropriately long timeouts for services that do polling or long-running queries.
  • Rate limit externally-exposed query endpoints to protect cluster performance from abusive or accidental query floods.
  • Periodically review which Couchbase services are actually proxied and shut down anything no longer in active use.

Couchbase’s split between HTTP-based services and its binary Data service protocol is the single most important thing to internalize before setting up a reverse proxy in front of it. Once that boundary is clear — proxy the console and query-style APIs, leave the Data service alone — the rest of the setup follows the same TLS-termination-plus-access-control pattern used for any other HTTP service behind Nginx.

Total
1
Shares

Leave a Reply

Previous Post
How to Set Up Nginx as a Reverse Proxy for Memcached

How to Set Up Nginx as a Reverse Proxy for Memcached

Next Post
How to Set Up Nginx as a Reverse Proxy for Redis

How to Set Up Nginx as a Reverse Proxy for Redis

Related Posts