Databases

Install RethinkDB on Ubuntu 24.04 / 22.04 and Debian 13 / 12

This guide shows how to install RethinkDB on Ubuntu 24.04 LTS and Debian 13 from the official apt repository, then configures a real instance, fronts the admin console with Nginx and Let’s Encrypt, and exercises the Python and Node.js drivers end-to-end. Every command was run fresh on an Ubuntu 24.04 OpenStack VM for this 2026 refresh. The same steps work unchanged on Ubuntu 22.04 LTS, Debian 12 (Bookworm), and Debian 13 (Trixie) because the repo publishes per-codename packages for all four.

Original content from computingforgeeks.com - post 16385

If you have never touched it: RethinkDB is an open-source NoSQL JSON document database whose claim to fame is server-pushed changefeeds. You subscribe to a query, and the database streams live updates whenever matching rows change. That’s exactly the feature that makes it worth keeping around in 2026 even with all the other document stores in the market. We’ll exercise it in the Node.js driver step below.

Tested April 2026 on Ubuntu 24.04 LTS (kernel 6.8) with RethinkDB 2.4.4 from the official apt repo. Repo also publishes 2.4.5 for the newer codenames (plucky, trixie) and 2.4.4 for noble, jammy, bookworm.

A note on project health before you commit: RethinkDB joined the Linux Foundation, relicensed under Apache 2.0, and the community ships sporadic bug-fix releases. If you are on the RHEL side of the house, the RethinkDB on RHEL/Rocky/Alma guide covers the parallel install path. The latest tagged release was 2.4.4 “Night of the Living Dead” in December 2024, with 2.4.5 builds now in the newer distro repos. It’s stable software but it’s not getting new features, and you should treat it as such when picking it for a greenfield project. For sustained heavy-realtime workloads it still works well; we’ll call out the production caveats in the hardening section at the end.

Prerequisites

  • A fresh Ubuntu 24.04 / 22.04 LTS or Debian 13 / 12 server with sudo access.
  • 2 GB RAM and 10 GB free disk. Cache is tuned from free RAM at start, so more is better.
  • Port 80 reachable from the internet if you want a real Let’s Encrypt cert (HTTP-01 challenge). A subdomain with an A record pointing at the server.
  • Ability to reach the driver port (28015) from wherever your app runs.

Set reusable shell variables

Every command below uses shell variables so you change one block at the top and paste the rest unchanged. Export these at the start of your SSH session:

export RDB_INSTANCE="cfg01"
export RDB_DOMAIN="rethinkdb.example.com"
export RDB_ADMIN_USER="cfgadmin"
export RDB_ADMIN_PASS="ChangeThisStrong2026!"
export RDB_ADMIN_EMAIL="[email protected]"

Swap in your real domain, pick a real admin password, and confirm the variables are set before running anything destructive:

echo "instance: ${RDB_INSTANCE}"
echo "domain:   ${RDB_DOMAIN}"
echo "email:    ${RDB_ADMIN_EMAIL}"

These variables hold only for the current shell. Re-export them if you reconnect or jump into sudo -i. Do not add RDB_ADMIN_PASS to /root/.bashrc; the Nginx htpasswd file below is the only place it needs to live.

Add the RethinkDB apt repository

RethinkDB’s Ubuntu and Debian binaries live at https://download.rethinkdb.com/repository/. The path suffix is the distro family plus the codename, and the repo ships separate trees per release, so one lsb_release -cs call picks the right one automatically on all four supported codenames.

Install the prerequisite packages first:

sudo apt update
sudo apt install -y curl gpg ca-certificates apt-transport-https lsb-release

Import the RethinkDB signing key into the modern /usr/share/keyrings/ location. The old apt-key add flow still works but prints deprecation warnings on 22.04 and above, and fails silently on some minimal images:

wget -qO- https://download.rethinkdb.com/repository/raw/pubkey.gpg | \
  sudo gpg --dearmor -o /usr/share/keyrings/rethinkdb-archive-keyring.gpg

Add the repository. The same line works on Ubuntu and Debian because the repo naming convention embeds the family (ubuntu- vs debian-) plus the codename:

DISTRO=$(. /etc/os-release; echo "$ID")
CODENAME=$(lsb_release -cs)
echo "deb [signed-by=/usr/share/keyrings/rethinkdb-archive-keyring.gpg] https://download.rethinkdb.com/repository/${DISTRO}-${CODENAME} ${CODENAME} main" | \
  sudo tee /etc/apt/sources.list.d/rethinkdb.list

You should see the line printed back with the correct distro and codename:

deb [signed-by=/usr/share/keyrings/rethinkdb-archive-keyring.gpg] https://download.rethinkdb.com/repository/ubuntu-noble noble main

For reference, the codenames currently served with RethinkDB 2.4.4 or 2.4.5 packages are:

DistributionCodenamePackage version
Ubuntu 25.04plucky2.4.5~0plucky
Ubuntu 24.04 LTSnoble2.4.4~0noble
Ubuntu 22.04 LTSjammy2.4.4~0jammy
Debian 13trixie2.4.5~0trixie
Debian 12bookworm2.4.4~0bookworm

Install the RethinkDB package

Refresh the apt cache and pull RethinkDB down:

sudo apt update
sudo apt install -y rethinkdb

Confirm the build version. This also doubles as a sanity check that the binary is in $PATH:

rethinkdb --version

On Ubuntu 24.04 LTS at the time of writing you get:

rethinkdb 2.4.4~0noble (x86_64-linux-gnu) (GCC 13.2.0)

Note that the service is not started automatically. The packaging ships a template init script at /etc/init.d/rethinkdb that spins up one process per config file it finds under /etc/rethinkdb/instances.d/, and that directory is empty by default. That behaviour is intentional, not a bug; it lets you run multiple instances on the same host with independent data directories.

RethinkDB 2.4.4 install and systemctl status on Ubuntu 24.04

Create and start a RethinkDB instance

Copy the shipped sample config into instances.d/. The filename without the .conf extension becomes the instance name, which in turn becomes the data directory name and the systemd log suffix. Keep it short:

sudo cp /etc/rethinkdb/default.conf.sample /etc/rethinkdb/instances.d/${RDB_INSTANCE}.conf

Tune three settings before the first start. Bind to all interfaces (or just localhost if you’re fronting with Nginx on the same box), expose the admin console on 8080, and give the server a stable name so systemd journal logs stay readable:

sudo sed -i \
  -e "s/^# bind=.*/bind=all/" \
  -e "s/^# http-port=.*/http-port=8080/" \
  -e "s/^# server-name=.*/server-name=${RDB_INSTANCE}/" \
  /etc/rethinkdb/instances.d/${RDB_INSTANCE}.conf

Verify the three lines are set (uncommented) before restarting the service:

sudo grep -E "^(bind|server-name|http-port)=" /etc/rethinkdb/instances.d/${RDB_INSTANCE}.conf

The three lines should print without a leading #, matching the values you just set:

bind=all
http-port=8080
server-name=cfg01

Start and enable the service. The generated systemd unit wraps the init script, so the same systemctl commands work as with any native unit:

sudo systemctl enable --now rethinkdb
sudo systemctl status rethinkdb --no-pager | head -15

A healthy start looks like this. Note the three /usr/bin/rethinkdb processes under cgroup control and the active (running) line:

● rethinkdb.service - LSB: This starts a set of rethinkdb server instances.
     Loaded: loaded (/etc/init.d/rethinkdb; generated)
     Active: active (running) since Thu 2026-04-23 15:09:49 UTC; 3s ago
       Docs: man:systemd-sysv-generator(8)
    Process: 2919 ExecStart=/etc/init.d/rethinkdb start (code=exited, status=0/SUCCESS)
      Tasks: 71 (limit: 4658)
     Memory: 21.0M (peak: 21.3M)
     CGroup: /system.slice/rethinkdb.service
             ├─3027 /usr/bin/rethinkdb --daemon --config-file /etc/rethinkdb/instances.d/cfg01.conf ...
             └─3028 /usr/bin/rethinkdb --daemon --config-file /etc/rethinkdb/instances.d/cfg01.conf ...

The three listener sockets you care about are 8080 (admin HTTP), 28015 (client driver), and 29015 (intra-cluster). Confirm all three are up:

sudo ss -tulnp | grep rethinkdb

All three sockets should appear, each owned by the rethinkdb process:

tcp LISTEN 0 256 *:8080  *:* users:(("rethinkdb",pid=3027,fd=23))
tcp LISTEN 0 256 *:28015 *:* users:(("rethinkdb",pid=3027,fd=22))
tcp LISTEN 0 256 *:29015 *:* users:(("rethinkdb",pid=3027,fd=21))

If a listener is missing, check the per-instance log first: sudo tail -40 /var/lib/rethinkdb/${RDB_INSTANCE}/data/log_file. The most common cause is a stale data directory from a previous instance; RethinkDB won’t auto-recreate it if a version mismatch is detected.

Lock the admin console down with UFW

Here is the sharp edge you have to know about: RethinkDB’s admin console has no built-in authentication. Anyone who can reach port 8080 can create and drop databases. The project’s official position is that 8080 is never meant to be exposed directly to the internet. If UFW is not already running, install and enable it first. UFW’s syntax is covered in more depth in common UFW firewall commands, but the rules you want here are:

sudo apt install -y ufw
sudo ufw allow OpenSSH
sudo ufw allow "Nginx Full"
sudo ufw allow from 10.0.0.0/8 to any port 28015 proto tcp comment 'RethinkDB driver from internal LAN only'
sudo ufw --force enable
sudo ufw status verbose

Swap 10.0.0.0/8 for whatever CIDR your app servers live in. The driver port should never be open to Anywhere; the wire protocol authenticates but is trivially fingerprinted. Port 29015 is only needed when you scale to multiple nodes, and then only between cluster members, not from clients.

Put the admin console behind Nginx with HTTPS and basic auth

The default apt setup installs Nginx and certbot’s nginx plugin. If you do not already have a working Nginx, the Nginx + Let’s Encrypt install guide covers the base setup. This flow uses the HTTP-01 challenge, which works with any DNS provider as long as port 80 resolves to the server, so Cloudflare is not required. If your box is on a private LAN or behind NAT, skip to the DNS-01 alternative at the end of this section.

sudo apt install -y nginx apache2-utils certbot python3-certbot-nginx

Create a password file for the admin user. Keep the file mode tight; only root and the www-data group need to read it:

sudo mkdir -p /etc/nginx/auth
sudo htpasswd -cb /etc/nginx/auth/rethinkdb.htpasswd "${RDB_ADMIN_USER}" "${RDB_ADMIN_PASS}"
sudo chmod 640 /etc/nginx/auth/rethinkdb.htpasswd
sudo chown root:www-data /etc/nginx/auth/rethinkdb.htpasswd

Drop a server block that proxies to 127.0.0.1:8080. The placeholder RDB_DOMAIN_HERE gets rewritten with sed right after so the file itself stays static:

sudo tee /etc/nginx/sites-available/rethinkdb >/dev/null <<'NGINX'
server {
    listen 80;
    server_name RDB_DOMAIN_HERE;
    location / { return 301 https://$host$request_uri; }
}

server {
    listen 443 ssl http2;
    server_name RDB_DOMAIN_HERE;

    # certbot will rewrite ssl_certificate/ssl_certificate_key paths below
    ssl_certificate     /etc/ssl/certs/ssl-cert-snakeoil.pem;
    ssl_certificate_key /etc/ssl/private/ssl-cert-snakeoil.key;

    auth_basic "RethinkDB Admin";
    auth_basic_user_file /etc/nginx/auth/rethinkdb.htpasswd;

    location / {
        proxy_pass http://127.0.0.1:8080;
        proxy_http_version 1.1;
        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 300s;
    }
}
NGINX

sudo sed -i "s/RDB_DOMAIN_HERE/${RDB_DOMAIN}/g" /etc/nginx/sites-available/rethinkdb
sudo ln -sf /etc/nginx/sites-available/rethinkdb /etc/nginx/sites-enabled/rethinkdb
sudo rm -f /etc/nginx/sites-enabled/default
sudo nginx -t && sudo systemctl reload nginx

The reference to the snakeoil cert is a placeholder so Nginx can start. Certbot overwrites those two lines when it issues the real cert:

sudo certbot --nginx \
  -d "${RDB_DOMAIN}" \
  --non-interactive --agree-tos --redirect \
  -m "${RDB_ADMIN_EMAIL}"

Certbot prints the cert path and expiry, schedules auto-renewal via a systemd timer, and reloads Nginx. You can confirm both sides with a curl round trip. The no-auth request should return 401, the authenticated one should return 200 and a chunk of the admin HTML:

curl -s -o /dev/null -w "%{http_code}\n" "https://${RDB_DOMAIN}/"
curl -s -o /dev/null -w "%{http_code}\n" -u "${RDB_ADMIN_USER}:${RDB_ADMIN_PASS}" "https://${RDB_DOMAIN}/"

Both codes confirm Nginx is proxying correctly and basic auth is enforced:

401
200

Open the URL in a browser and log in with the admin credentials you set in the Step 1 variables. You get a real-time cluster dashboard with connection status, table counts, cache usage, and a reads/writes graph:

RethinkDB admin dashboard cluster health on Ubuntu 24.04

Alternative: DNS-01 for private or NAT’d servers

If port 80 is not reachable from the internet (home lab, VPN, strict security group), use the DNS-01 challenge instead. Certbot ships plugins for Cloudflare, Route 53, DigitalOcean, Google Cloud DNS, Linode, and OVH; apt search python3-certbot-dns- lists what’s packaged on your distro. The Cloudflare plugin is the shortest to demo, but swap in your provider’s plugin and credential file format:

sudo apt install -y python3-certbot-dns-cloudflare
echo "dns_cloudflare_api_token = YOUR_TOKEN_HERE" | sudo tee /etc/letsencrypt/cloudflare.ini
sudo chmod 600 /etc/letsencrypt/cloudflare.ini
sudo certbot certonly --dns-cloudflare \
  --dns-cloudflare-credentials /etc/letsencrypt/cloudflare.ini \
  -d "${RDB_DOMAIN}" \
  --non-interactive --agree-tos -m "${RDB_ADMIN_EMAIL}"

After DNS-01 issues, point the Nginx ssl_certificate pair at /etc/letsencrypt/live/${RDB_DOMAIN}/fullchain.pem and privkey.pem manually, then reload. The auto-renewal timer picks up the DNS-01 plugin the same way as HTTP-01.

Connect to RethinkDB with the Python driver

The official Python driver is on PyPI as rethinkdb. It’s pure Python and works on any 3.x you have installed; for a clean setup guide see install Python 3.13 on Ubuntu. Use a virtualenv so you do not fight the system’s PEP 668 “externally-managed” lock:

sudo apt install -y python3-venv python3-pip
mkdir -p ~/rtest && cd ~/rtest
python3 -m venv venv
source venv/bin/activate
pip install rethinkdb

Run a full round trip: connect, create a database and table, insert documents, query them back, and print them. Save this as demo.py:

import rethinkdb as r
conn = r.r.connect(host="localhost", port=28015)

r.r.db_create("blog_demo").run(conn)
r.r.db("blog_demo").table_create("posts").run(conn)

r.r.db("blog_demo").table("posts").insert([
    {"title": "Hello RethinkDB", "author": "cfg", "views": 42},
    {"title": "Realtime changefeeds", "author": "cfg", "views": 108},
]).run(conn)

for doc in r.r.db("blog_demo").table("posts").run(conn):
    print(doc)

Run it:

python3 demo.py

You get back the two rows you just inserted, each with a generated UUID primary key:

{'author': 'cfg', 'id': '49a19dfc-3f58-4932-9f83-d1df75384c2d', 'title': 'Hello RethinkDB', 'views': 42}
{'author': 'cfg', 'id': '597f444c-da48-4fb9-88df-31d86fa1e749', 'title': 'Realtime changefeeds', 'views': 108}

Here is the same sequence captured from the terminal so you can match it against your own output:

RethinkDB Python driver insert and query example on Ubuntu 24.04

Open the admin console’s Tables tab and the new blog_demo database appears with its posts table, 1 shard and 1 replica (single-node defaults), shown as Ready:

RethinkDB admin Tables view blog_demo posts on Ubuntu 24.04

Connect with the Node.js driver and consume a changefeed

Changefeeds are the one feature you cannot replicate easily with other NoSQL document stores. The Node.js driver’s .changes() call subscribes to a query and streams every insert, update, and delete as they happen. Install Node 20 LTS from NodeSource, then pin the official driver:

curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt install -y nodejs
node --version
cd ~/rtest
npm init -y
npm install rethinkdb

Save this as realtime.js. It subscribes to the posts table, then inserts a fresh row after one second. The subscriber logs the change event and exits:

const r = require("rethinkdb");

async function main() {
  const conn = await r.connect({ host: "localhost", port: 28015 });
  const change = await r.db("blog_demo").table("posts").changes().run(conn);
  console.log("subscribed to changefeed");

  setTimeout(() => {
    r.db("blog_demo").table("posts").insert({
      title: "New post from Node driver",
      author: "cfg",
      views: 1,
    }).run(conn);
  }, 1000);

  change.each((err, row) => {
    if (err) throw err;
    console.log("change event:", JSON.stringify(row));
    conn.close();
    process.exit(0);
  });
}

main().catch((e) => { console.error(e); process.exit(1); });

Running it prints the subscribe message, then a single change event containing the new row. old_val is null because this is an insert, not an update:

subscribed to changefeed
change event: {"new_val":{"author":"cfg","id":"af9fb10f-29ea-445b-b0ff-9bf1a0a656cf","title":"New post from Node driver","views":1},"old_val":null}

Update instead of insert and you’d see both old_val and new_val. That is the entire contract: you plug a socket into any query and the database tells you what changed.

Troubleshooting real errors from this build

Error: “E: The repository ‘https://download.rethinkdb.com/repository/… noble Release’ does not have a Release file.”

You ran apt update before importing the GPG key, or the key landed in the wrong path. Confirm the key file exists and the signed-by= path in /etc/apt/sources.list.d/rethinkdb.list matches exactly. The older /etc/apt/trusted.gpg.d/ pattern is deprecated on 22.04 and up; use /usr/share/keyrings/.

Error: “instance1: Failed to start. Log: could not create directory ‘/var/lib/rethinkdb/instance1/data'”

The rethinkdb Unix user (created by the package) does not own the parent directory. This happens when you extract a backup or move the data directory manually. Fix with:

sudo chown -R rethinkdb:rethinkdb /var/lib/rethinkdb/

Error: “rethinkdb.errors.ReqlDriverError: Could not connect to localhost:28015”

Usually the service did not start (check systemctl status rethinkdb) or it’s bound to a non-default port. The config file’s driver-port= setting must match the client’s port. Also check that the firewall is not dropping local 28015 traffic on hosts with strict lo rules, though this is rare on Ubuntu.

Error: “rethinkdb: server name contains invalid characters”

The server-name= value only accepts lowercase letters, digits, and underscores. Hyphens and dots are rejected. Rename the instance to cfg01, db_node_1, or similar, then restart.

Error: “rethinkdb admin UI shows 405 Method Not Allowed behind Nginx”

Harmless for HEAD requests (the admin SPA doesn’t implement HEAD). Fetch with curl -sG or open the URL in a browser; you’ll see the real HTML with a 200 status.

Production hardening checklist

Everything above is enough to stand up a working RethinkDB node. Before you put it under real traffic, walk this list:

  • Never expose 8080 to the internet directly. The admin console has no native auth. Nginx + basic auth + Let’s Encrypt is the minimum; fronting it with a VPN or SSO proxy is better.
  • Enable driver-level auth: rethinkdb set-passwd inside the admin console’s Data Explorer sets an admin account password that drivers must supply with r.connect({user:"admin", password:"..."}). The default is empty, which is an automated ransom attack waiting to happen.
  • Back up the data directory, not just a dump. The directory under /var/lib/rethinkdb/${RDB_INSTANCE}/data is the source of truth. A stopped-instance tar is the simplest backup; rethinkdb dump produces a .tar.gz but can stall on large tables.
  • Cap cache size in rethinkdb.conf with cache-size=1024 (megabytes) if the server shares RAM with other services. The automatic value is ~50% of free RAM at start, which is aggressive.
  • Set no-update-check=true in the config. The upstream update pinger is on by default and sends your hostname and version to update.rethinkdb.com. Not a security issue, but not what you want on a private host.
  • Plan for the project’s cadence. RethinkDB ships bug fixes a few times a year and no major new features. If you need maturity without active feature development, that’s fine; if you need vendor-backed evolution, look at ArangoDB, RavenDB, or Dgraph as alternatives with different trade-offs.
  • Monitor the three listener ports. A Prometheus node_exporter with the textfile collector plus a ss -tulnp cron job is the dumbest thing that works. If any of 8080, 28015, or 29015 disappear, page the on-call.

That’s the short list that actually matters in 2026. Harden it, back it up, and RethinkDB will sit there and do its job for years.

Related Articles

Databases Install Ajenti Control Panel on Ubuntu 18.04 LTS Containers Install Apptainer (Singularity) on Rocky Linux 10 / AlmaLinux 10 / Ubuntu 24.04 Ubuntu Install NoMachine RDP on Ubuntu 22.04|20.04|18.04 VOIP Install Festival TTS for Asterisk on Ubuntu 24.04

1 thought on “Install RethinkDB on Ubuntu 24.04 / 22.04 and Debian 13 / 12”

Leave a Comment

Press ESC to close