Resistro Cloud Documentation
Resistro Cloud is a managed backup baseline for small self-managed PostgreSQL databases. EU-hosted, E2E encrypted, starting at 9€/month.
Quick Start
Get your first backup running in under 5 minutes:
# 1. Install the cloud agent (installs the binary and the systemd unit) curl -fsSL https://cloud.resistro.org/install-agent.sh | sudo sh # 2. Put your credentials in the environment file (mode 0600, never on the command line) sudo $EDITOR /etc/resistro-agent/env # RESISTRO_API_KEY=... from the dashboard, "API Key" # RESISTRO_ENCRYPTION_KEY=... generate once: openssl rand -hex 32 # 3. Start the agent sudo systemctl enable --now resistro-agent sudo journalctl -u resistro-agent -f # That's it. The agent asks for work hourly; how often a backup actually # runs depends on your plan - daily on Solo and Starter, hourly from # Business upward.
--upload=true) and refuses to start without an encryption key — it will not silently fall back to storing your data unencrypted.
Install the Agent
The agent is a single static binary (Linux amd64 and arm64) with no runtime dependencies of its own. It talks to your database with the engine's own tools (pg_dump, mysqldump), connects to cloud.resistro.org, reports backup status, and uploads encrypted backups.
The recommended way is the installer — it detects your architecture, pins the expected SHA-256 of the release build, verifies the download against it, creates /etc/resistro-agent/env with mode 0600, and installs the systemd unit:
curl -fsSL https://cloud.resistro.org/install-agent.sh | sudo sh
Manual download — the block below performs the same checksum verification the installer does, by reading the expected SHA-256 out of the installer instead of asking you to compare two hex strings by eye. Run it as written; the || branch aborts before the binary is made executable:
# Download (Linux amd64 — for arm64 replace both occurrences of amd64 with arm64) wget https://cloud.resistro.org/download/resistro-agent_linux_amd64 # Expected checksum, taken from the installer — the same value the installer pins EXPECTED=$(curl -fsSL https://cloud.resistro.org/install-agent.sh \ | sed -n 's/^EXPECTED_SHA256_AMD64="\(.*\)"$/\1/p') [ -n "$EXPECTED" ] || { echo "could not read expected checksum - aborting"; exit 1; } # Verify. On systems without sha256sum (e.g. macOS) use: shasum -a 256 -c - echo "$EXPECTED resistro-agent_linux_amd64" | sha256sum -c - \ || { echo "CHECKSUM MISMATCH - do not run this binary"; exit 1; } chmod +x resistro-agent_linux_amd64 mv resistro-agent_linux_amd64 /usr/local/bin/resistro-cloud-agent
curl | sh installer sits on. If you need provenance independent of this host, verify the release checksum against the one published with the release before you install.
Connect to Cloud
Find your API key in the dashboard under "API Key".
Pass the API key and the encryption key through the environment, never as command-line flags — process arguments are world-readable via ps and /proc/<pid>/cmdline. The agent warns when you use --api-key for exactly this reason.
# Credentials file — the installer already creates this. Only run the block below # on a host that has no /etc/resistro-agent/env yet: it overwrites the file and # would replace an existing encryption key, making earlier backups unrecoverable. cat > /etc/resistro-agent/env <<EOF RESISTRO_API_KEY=rst_your_key_here RESISTRO_ENCRYPTION_KEY=$(openssl rand -hex 32) EOF chmod 600 /etc/resistro-agent/env # Run interactively (same variables, same process) set -a; . /etc/resistro-agent/env; set +a resistro-cloud-agent --backup-interval 1h # Run as systemd service cat > /etc/systemd/system/resistro-agent.service <<EOF [Unit] Description=resistro-agent — backup daemon for resistro.org SaaS Documentation=https://cloud.resistro.org/docs After=network-online.target Wants=network-online.target [Service] Type=simple EnvironmentFile=/etc/resistro-agent/env ExecStart=/usr/local/bin/resistro-cloud-agent --heartbeat-interval 60s --backup-interval 1h Restart=on-failure RestartSec=30 [Install] WantedBy=multi-user.target EOF systemctl daemon-reload systemctl enable --now resistro-agent
Agent Options
| Flag | Env | Default | Description |
|---|---|---|---|
--api-key | RESISTRO_API_KEY | required | Your API key from the dashboard. Prefer the env variable or --api-key-file; passed as a flag the secret is visible in ps//proc and the agent logs a warning. |
--api-key-file | Read the API key from a file instead of the command line | ||
--server | RESISTRO_SERVER | https://cloud.resistro.org | Server URL |
--heartbeat-interval | RESISTRO_HEARTBEAT_INTERVAL | 1m | Agent heartbeat interval |
--backup-interval | RESISTRO_BACKUP_INTERVAL | 1h | How often the agent asks for backup work; set 0 to disable the daemon backup loop. The server decides whether a run is due: on Solo and Starter a new backup is accepted once the previous one is at least 20 hours old (about one per day), Business and Pro have no spacing. A request inside your plan's window is answered with a clean skip (tier_backup_frequency), not an error. |
--backup-engine | RESISTRO_BACKUP_ENGINE | tools | Deprecated; the agent selects direct database tools per engine (pg_dump for PostgreSQL, mysqldump for MySQL/MariaDB). |
--interval | Deprecated alias for --backup-interval | ||
--encryption-key | RESISTRO_ENCRYPTION_KEY | required while --upload is true | Hex-encoded 256-bit AES key. Prefer the env variable or --encryption-key-file; passed as a flag the secret is visible in ps//proc. |
--encryption-key-file | RESISTRO_ENCRYPTION_KEY_FILE | Read the encryption key from a file instead of the command line | |
--upload | true | Upload backups to cloud storage. While true the agent exits at startup if no encryption key is set. | |
--include-system-dbs | RESISTRO_INCLUDE_SYSTEM_DBS | false | Also back up engine-internal DBs (postgres, template0, mysql, information_schema, ...) |
openssl rand -hex 32 and put it in /etc/resistro-agent/env. Save it somewhere safe. Without the key, your backups are unrecoverable — we cannot help you recover them.
Register / Login
Create an account at cloud.resistro.org or via API:
# Register curl -X POST https://cloud.resistro.org/api/v1/auth/register \ -H "Content-Type: application/json" \ -d '{"email":"you@example.com","password":"secret","name":"Your Name"}' # Login curl -X POST https://cloud.resistro.org/api/v1/auth/login \ -H "Content-Type: application/json" \ -d '{"email":"you@example.com","password":"secret"}'
Both return a JWT token and your API key.
Manage Databases
# Add a database curl -X POST https://cloud.resistro.org/api/v1/databases \ -H "Authorization: Bearer YOUR_TOKEN" \ -H "Content-Type: application/json" \ -d '{"name":"myapp_prod","engine":"postgresql"}' # List databases curl https://cloud.resistro.org/api/v1/databases \ -H "Authorization: Bearer YOUR_TOKEN"
View Backups
# List all backups curl https://cloud.resistro.org/api/v1/backups \ -H "Authorization: Bearer YOUR_TOKEN" # Filter by database curl "https://cloud.resistro.org/api/v1/backups?database_id=UUID" \ -H "Authorization: Bearer YOUR_TOKEN" # Dashboard overview curl https://cloud.resistro.org/api/v1/dashboard \ -H "Authorization: Bearer YOUR_TOKEN"
Configure Alerts
# Add email alert (on failure + anomaly) curl -X POST https://cloud.resistro.org/api/v1/alerts \ -H "Authorization: Bearer YOUR_TOKEN" \ -H "Content-Type: application/json" \ -d '{"channel":"email","target":"ops@example.com"}' # Add Slack webhook curl -X POST https://cloud.resistro.org/api/v1/alerts \ -H "Authorization: Bearer YOUR_TOKEN" \ -H "Content-Type: application/json" \ -d '{"channel":"slack","target":"https://hooks.slack.com/services/xxx","on_success":true}' # List alerts curl https://cloud.resistro.org/api/v1/alerts \ -H "Authorization: Bearer YOUR_TOKEN" # Delete alert curl -X DELETE https://cloud.resistro.org/api/v1/alerts/ALERT_ID \ -H "Authorization: Bearer YOUR_TOKEN"
Alert channels: email, slack, teams, webhook
Toggles: on_failure (default: true), on_success (default: false), on_anomaly (default: true)
API Reference: Authentication
| Endpoint | Auth | Description |
|---|---|---|
| POST/api/v1/auth/register | None | Create account |
| POST/api/v1/auth/login | None | Login, get JWT |
API Reference: Databases
| Endpoint | Auth | Description |
|---|---|---|
| GET/api/v1/databases | JWT | List databases |
| POST/api/v1/databases | JWT | Add database |
| PATCH/api/v1/databases/{id} | JWT | Update database settings |
API Reference: Backups
| Endpoint | Auth | Description |
|---|---|---|
| GET/api/v1/backups | JWT | List backups (?database_id= filter) |
| GET/api/v1/dashboard | JWT | Stats overview |
API Reference: Alerts
| Endpoint | Auth | Description |
|---|---|---|
| GET/api/v1/alerts | JWT | List alert configs |
| POST/api/v1/alerts | JWT | Create alert config |
| DELETE/api/v1/alerts/{id} | JWT | Delete alert config |
API Reference: Agent
| Endpoint | Auth | Description |
|---|---|---|
| POST/api/v1/agent/heartbeat | API Key | Agent heartbeat |
| POST/api/v1/agent/backup/start | API Key | Start backup record |
| POST/api/v1/agent/backup/complete | API Key | Complete backup record |
| PUT/api/v1/agent/backup/{id}/upload | API Key | Upload encrypted backup data |
Agent endpoints use X-API-Key header. Dashboard endpoints use Authorization: Bearer TOKEN.
Encryption
All backups uploaded to Resistro Cloud are encrypted before leaving your server using AES-256-GCM with a random nonce per backup. The encryption key never leaves your machine.
# Generate your key once, put it in /etc/resistro-agent/env: openssl rand -hex 32 RESISTRO_ENCRYPTION_KEY=a1b2c3d4...hex... # Save it somewhere safe (password manager, hardware token). # Without this key, your backups are unrecoverable. # We cannot decrypt your backups — by design.
Restore
Two steps: download the encrypted backup, then decrypt and pg_restore.
1. List backups
curl -H "Authorization: Bearer $TOKEN" \
https://cloud.resistro.org/api/v1/backups
2. Download + decrypt
Use the customer-restore.sh helper or do it by hand:
# Download ciphertext curl -o backup.enc -H "Authorization: Bearer $TOKEN" \ https://cloud.resistro.org/api/v1/backups/<BACKUP_ID>/download # Decrypt locally (build decrypt-backup from the resistro-cloud repo) decrypt-backup -key $RESISTRO_ENCRYPTION_KEY -in backup.enc -out backup.dump # Restore into your target Postgres pg_restore -h <host> -U <user> -d <target_db> --no-owner backup.dump
The download endpoint streams raw ciphertext — the server cannot decrypt it. Keep the encryption key.
Storage Backends
Resistro Cloud supports multiple storage backends:
| Backend | Description | Plan |
|---|---|---|
local | Hetzner Storage Box (default) | All plans |
s3 | S3-compatible (AWS, MinIO, Wasabi) | Business+ |
sftp | SFTP server (bring your own) | Business+ |
© 2026 Resistro · resistro.org · Dashboard