Skip to content
Rowsafe

Your database, your data, your keys.

Rowsafe sits next to the most important thing you run. Here is how it stays out of harm's way.

  • We ask before we change anything

    Rowsafe shows you a plan first and changes nothing until you approve it.

  • We never restart your database

    The one restart needed to turn Rowsafe on is yours to schedule.

  • Your data stays yours

    Backups are encrypted on your server with a key only you hold, and stored in your own storage. We never see what's inside.

  • Nothing can reach in

    The agent only makes outgoing connections. Nothing on your server listens for us.

  • Updates are signed and tested

    The agent only runs updates we signed, tests each one first, and rolls back on its own if one misbehaves.

  • Restore checks stay private

    Weekly restore checks run in an isolated copy on your own server that nothing can connect to, then it's deleted.

  • Open source where it counts

    Everything that runs on your servers is open source, so you can read every line.

The details

For your security review. The security docs go further.

What Rowsafe could and couldn't do if it were compromised

It could

  • Queue the fixed tasks for your databases: plans, backups, checks, drills, restore points, and applying an adopt plan (the archiving settings only).
  • Read metadata: hostnames, database names and sizes, table counts, PostgreSQL settings, task logs, and the monitoring data the agent reports (connection and lock counts, normalized query statistics from pg_stat_statements, disk and host metrics).
  • Withhold agent updates, or offer a release that is signed but bad. Agents still self-test it, put it on probation and roll back.

It could not

  • Run arbitrary commands or SQL on your database host.
  • Read or write backup contents, or reach your bucket at all.
  • Make an agent run a binary that was not signed with the release key, or downgrade an agent.
  • Restart or stop PostgreSQL, drop data, or change settings other than the archiving settings.

Where every secret lives

CredentialHeld byGrants
API key (rsk_)You, the CLI, the dashboardThe user API for one organization. Can be read-only.
Enrollment token (rse_)The installer, onceEnrolling one host. Single use, expires after 1 hour by default.
Agent token (rsa_)/var/lib/rowsafe/agent.json on the host (0600)The agent API for that one host.
Bucket key and secret/etc/rowsafe on the host (0600)Your bucket. Never sent to Rowsafe.
Encryption passphraseThe host and your secret managerDecrypting every backup. Never sent to Rowsafe.
Release signing keyThe release process, never the control planeProducing agent builds that agents accept.

Keep the encryption passphrase in your secret manager before the first backup exists. Without it no backup can be restored, by anyone.

How the agent runs on your server

Plan before apply
Adopting a database prints a read-only plan. Nothing changes until you run rowsafe apply, and an existing archive_command is never replaced without --force.
Never restarts PostgreSQL
Settings that need a restart are written with ALTER SYSTEM. You restart in your own maintenance window, then verify.
Isolated drills
Drill clusters listen on a private Unix socket only, run with archiving off at low CPU and IO priority, and are deleted afterwards.
Signed updates, probation, rollback
The agent runs only releases signed with an Ed25519 key compiled into it. It refuses downgrades, self-tests a new version, and rolls back one that fails.
Secrets stay on your host
Bucket credentials and the encryption passphrase live in /etc/rowsafe on the database host (mode 0600). The control plane never receives them.
Client-side encryption
Backups and WAL are encrypted with aes-256-cbc before they leave the host. Your bucket holds only ciphertext.
Outbound only
The agent makes outbound HTTPS requests and listens on nothing. It runs one of a fixed set of tasks and never executes commands sent to it.
Open-source agent
Everything that runs on your servers (agent, CLI, installer) is open source under Apache-2.0, so you can audit every line that touches your database.
  • Runs as the postgres user under systemd with NoNewPrivileges, no capabilities, a private /dev and a read-only /usr and /etc (except /etc/rowsafe). It refuses to run as root.
  • Connects to PostgreSQL only over the Unix socket with peer authentication.
  • The kernel's OOM killer prefers the agent over production PostgreSQL, and the agent gets half the default CPU and IO weight.
  • Tokens are 32 random bytes. The control plane stores only their SHA-256 hashes.

How agent updates are signed, tested and rolled back

  1. Offer: the control plane offers a release in the heartbeat response, following the host's channel, pin and the release's rollout percentage.

  2. Verify: the agent checks the Ed25519 signature on the manifest with its compiled-in key and refuses anything that is not newer.

  3. Stage: between tasks only, it downloads the binary and checks its size and SHA-256 against the signed manifest.

  4. Self-test: the new binary must load the configuration, find pgBackRest, reach the control plane and connect to every watched database.

  5. Switch: the symlink is swapped atomically and systemd starts the new version.

  6. Probation: the new version claims no work until it has run for 60 seconds with a successful heartbeat. If it can't get there, it is rolled back, and the rollout halts for every host.

How weekly restore checks stay isolated

  1. Checks free disk first: at least 1.3 × the cluster size + 1 GiB, or the drill refuses to start.

  2. Restores the latest backup plus every archived WAL segment with pgbackrest restore, at low CPU and IO priority, with archiving off.

  3. Starts the copy on a private Unix socket with no TCP listener, and waits for recovery to finish.

  4. Compares every database with production. A missing database, or one restored empty, fails the drill.

  5. Stops the scratch cluster and deletes its directory, whatever the outcome.

Reporting a vulnerability

Report it privately through GitHub's private vulnerability reporting on the Rowsafe repository, with the details and how to reproduce them. Please give us a chance to fix it before you disclose it. For anything else, email hello@rowsafe.sh.

Agent & CLI on GitHub

Protect your first database today.

Free for one server and three databases. Upgrade when you add more.

Start free