Instructions

From a fresh checkout or a fresh server to an application talking to Propus.

On this page: Build from source · Run locally · Install on a server · Create a database · Connect · Behind a reverse proxy · Backups and restore · Upgrade and roll back · Lost password · Rotate the encryption key

Build from source

Needs Rust (stable) and Node.js 20+. The Control Center is built first because the binary embeds it.

git clone https://github.com/starrvarse/propus && cd propus
(cd console && npm ci && npm run build)
cargo build --release                       # target/release/propus

A static Linux binary (what releases ship):

rustup target add x86_64-unknown-linux-musl
cargo build --release --target x86_64-unknown-linux-musl -p propus-server

Run locally

./target/release/propus init  --data ./data                 # prints the admin key once, and the setup link
./target/release/propus serve --data ./data \
  --pg-listen 127.0.0.1:7932 --cache-listen 127.0.0.1:7933 --kafka-listen 127.0.0.1:7934

The console is at http://127.0.0.1:7900. Open the setup link from init (or run propus setup-link --data ./data for a new one) and create the owner account. There is one account per server; the link works once.

Add --encrypt --key-file ./master.key to init to encrypt data at rest. Keep the key file away from the data and its backups.

Install on a server

Linux x86_64 or aarch64 with systemd, as root:

curl -fsSLO https://pub-26c7c20a580e4d74ad4e962226f4d858.r2.dev/propus/install.sh
sudo bash install.sh --url https://pub-26c7c20a580e4d74ad4e962226f4d858.r2.dev/propus --public-url https://db.example.com \
  --pg-port 5432 --redis-port 6379 --kafka-port 9092

Releases are published at https://pub-26c7c20a580e4d74ad4e962226f4d858.r2.dev/propus (the latest) and https://pub-26c7c20a580e4d74ad4e962226f4d858.r2.dev/propus/<version> (each version, e.g. --version 0.2.0). Each holds propus-<version>-<arch>-linux.tar.gz for x86_64 and aarch64 (a stripped, static binary, about 13 MB), SHA256SUMS with its Ed25519 signature SHA256SUMS.sig, install.sh, and propus-<version>-<arch>-linux.debug (the binary's debug symbols, for reading crash traces; not installed).

The installer:

  1. checks CPU, memory, disk, the port and privileges;
  2. downloads the release and verifies SHA256SUMS.sig against the Propus release key, then the archive's checksum, so nothing unverified runs;
  3. creates the unprivileged propus account, which owns only /var/lib/propus;
  4. initializes storage, encrypted by default (/etc/propus/master.key);
  5. sets up TLS (your --tls-cert/--tls-key, or a self-signed certificate);
  6. opens the ports in ufw or firewalld if one is active (--no-firewall to skip);
  7. turns on daily verified backups (--backup-every, --backup-keep);
  8. installs a sandboxed systemd service, waits for the health check, and prints the setup link.
WhereWhat
/usr/local/bin/propusThe binary (propus.previous after an upgrade)
/etc/propus/propus.envSettings (PROPUS_*)
/etc/propus/admin-keyServer admin key, root only
/etc/propus/master.keyEncryption key
/etc/propus/tls/Certificate and key
/var/lib/propus/datasystem.propus and databases/<name>.propus
/var/lib/propus/backupsScheduled backups

systemctl status propus and journalctl -u propus show the service.

Create a database

In the console press New database, or with the admin key:

curl -s https://db.example.com/v1/databases -H "Authorization: Bearer $(sudo cat /etc/propus/admin-key)" \
  -H 'content-type: application/json' -d '{"name":"shop"}'

The answer holds the database's key and its URLs, shown once. The database's overview page shows them again and can reset the key.

Connect

ClientURL
Propus SDKs, AutoGraph, propus migratepropus://shop:<secret>@db.example.com/shop (propus+http:// without TLS)
psql, node-postgres, Drizzlepostgres://shop:<secret>@db.example.com:5432/shop?sslmode=verify-full
redis-cli, ioredis, node-redisrediss://:<secret>@db.example.com:6379
kafkajs, librdkafkabroker db.example.com:9092, SASL_SSL PLAIN, user shop, password <secret>
AWS SDKsendpoint https://db.example.com/s3, access key and secret from the console
import { Propus } from "@propus/client";
const db = new Propus(process.env.PROPUS_URL);
await db.query("CREATE TABLE notes (id SERIAL PRIMARY KEY, body TEXT)");
await db.query("INSERT INTO notes (body) VALUES ($1)", ["hello"]);

New tables have row-level security on: the database's own key is an admin and sees everything; keys made for a role and tenant see nothing until a policy allows it. See security.md.

Behind a reverse proxy

When a proxy such as Caddy or nginx already owns port 443, run Propus on loopback and give the proxy the HTTPS side. The Postgres, Redis and Kafka protocols are not HTTP, so Propus serves them itself with the same certificate:

propus serve --data /var/lib/propus/data --listen 127.0.0.1:7900 --public-url https://db.example.com \
  --pg-listen 0.0.0.0:5432    --pg-public db.example.com:5432 \
  --cache-listen 0.0.0.0:6379 --cache-public db.example.com:6379 \
  --kafka-listen 0.0.0.0:9092 --kafka-public db.example.com:9092 \
  --protocol-tls-cert /etc/propus/tls/cert.pem --protocol-tls-key /etc/propus/tls/key.pem
db.example.com {
    reverse_proxy 127.0.0.1:7900
}

Copy the proxy's certificate to the --protocol-tls-* files when it renews (a daily timer is enough); Propus reloads them without a restart.

Backups and restore

  • Scheduled: --backup-dir (on by default when installed). Each backup is opened and integrity-checked before it counts; the newest --backup-keep are kept.
  • On demand: the console's Data safety page, or POST /v1/db/<name>/backups.
  • Offline: propus backup --database shop --out shop.bak with the server stopped.
  • Restore: stop the server, then propus restore --database shop --backup shop.bak. The backup's SHA-256 manifest is checked first.

POST /v1/db/<name>/verify (or Data safety › Verify) checks every row, key, index, foreign key and check rule against each other.

Upgrade and roll back

sudo bash install.sh --upgrade --url https://pub-26c7c20a580e4d74ad4e962226f4d858.r2.dev/propus     # rolls back by itself if unhealthy
sudo bash install.sh --rollback                                      # back to the previous version

Data stays in place across upgrades and rollbacks.

Lost password

On the server: sudo propus recovery-link --email <owner email>. Open the link and set a new password.

Rotate the encryption key

sudo systemctl stop propus
sudo propus rotate-key --key-file /etc/propus/master.key --new-key-file /etc/propus/master.key.new
sudo mv /etc/propus/master.key.new /etc/propus/master.key && sudo chown root:propus /etc/propus/master.key && sudo chmod 640 /etc/propus/master.key
sudo systemctl start propus

Only the data key is re-wrapped, so this is quick at any size.

Moving in from another system

propus migrate --from postgres://app:pass@old-host/app --to "$PROPUS_URL"
propus migrate status  --to "$PROPUS_URL"
propus migrate cutover --to "$PROPUS_URL" --id <id>

It inspects the source, copies, follows changes, verifies every row, and on cutover makes the source read-only. rollback writes Propus's later changes back to the source. Every source and option is in commands.md.