From → To transfers
from-tosourceKinddestinationKindlocal|server|s3|peer
Every backup is a transfer between endpoints. Sources: local host, SSH server, or S3 object prefix. Destinations: local, server, S3, or Bro peer.
- Directions include local↔local, local↔server, server↔server, and any side with S3 (S3 sources are path/prefix only).
- Default for new jobs remains Server → Local under /backups/<server-slug>/<backup-slug>.
- Destination uniqueness is per endpoint: local path, (destinationServerId, path), or (destinationS3ProfileId, prefix).
Source types
source-typespathdocker_volumedatabaselazybackup_instance
Four source types. Destinations are always paths or object prefixes—never “to a volume.”
- path — filesystem tree or S3 prefix; rsync preferred, scp fallback.
- docker_volume — named volume on a source server or this host’s Docker socket; alpine packs .tar.gz (not a consistent live-DB backup).
- database — Postgres / MySQL / MariaDB logical dump → .sql.gz via native client or docker exec (local or server). SQLite → .sqlite.gz (native file / sqlite3 .backup only).
- lazybackup_instance — packs SQLite + age vault + SSH keys; optional age passphrase wrap (not the instance age key).
Server → Server (direct or relay)
server-to-serverephemeral SSHrelay
When both ends are servers, prefer a direct path so data does not bounce through the backup host.
- Installs an ephemeral SSH key on the destination so the source can rsync directly.
- If the source cannot reach the destination, LazyBackup relays: pull to the host, then push.
- S3 transfers always relay via the LazyBackup host. Ephemeral keys are cleaned up after the run.
S3-compatible profiles
s3@aws-sdk/client-s3forcePathStyle
MinIO, Cloudflare R2, Backblaze B2, AWS, and other S3-compatible endpoints as source prefixes or destinations.
- Custom endpoint + region + path-style for MinIO/R2/B2.
- S3 sources only support sourceType=path (object prefix).
- Encrypted artifacts and instance archives land as ordinary objects under a prefix.
age encryption vault
encryptionage_keysrecovery recipientsenableEncryption
Optional client-side age encryption before land. Bro destinations force encryption. Private identities stay on this instance.
- Vault statuses: active (used for new encrypts), retired, compromised—decrypt tries all stored identities.
- Create new key demotes the previous active to retired (never silent overwrite).
- Every encrypt includes the active recipient plus all recovery recipients (offline age1… keys).
- Passphrase-wrapped identity export for password managers; export acknowledgment checklist + Status nag when missing.
Bro Space
brodestinationKind=peermailboxLazyBro/api/peers
1:1 reciprocal peer storage. Mailbox sync + LazyBro outbound agent; invite-code pairing. Encryption forced; offline sync is soft status.
- Land stages age ciphertext locally; peer pulls via /api/peers/agent/* then acks (new pairs = mailbox).
- LazyBro is outbound-only (mode=client, empty remote URL)—only your LazyBackup needs inbound reachability; LB↔LB both need URLs and both run the sync worker.
- Invite + Accept (or paste in LazyBro); hard quotas; opaque blobs; Bro offline / sync pending does not fire failure webhooks.
- Mailbox retention uses the same version-count and age/min-keep rules as S3. LazyBackup advertises deletes[]; LazyBro unlinks and acks. Open recalls are skipped until they finish.
- Restore/download while the blob is still on the peer returns HTTP 202 (waiting)—keep LazyBro running so the recall can finish. Not a backup failure.
- Download LazyBro: https://github.com/Ceneka/lazybackup/releases/tag/lazybro (linux-x64, linux-arm64, darwin-arm64, darwin-x64, windows-x64).
- Optional Tailscale on the LazyBackup host (not bundled in the image) so friends can dial a 100.x address.
Instance meta-backup
instance-backuplazybackup_instanceinstanceBackupPassphrase
Back up LazyBackup itself: SQLite database, age vault secrets, and SSH key rows—schedulable like any other job.
- Settings → Encryption links to New Backup prefilled with source=lazybackup_instance.
- Optional passphrase wraps the tarball with age setPassphrase (avoids encrypting the vault with a key stored inside it).
- Cannot use Bro destinations. Restore is manual (replace DB / import keys)—no in-place auto-restore.
Status posture
statusGET /api/status/status
Operator checklist derived from stored config—not a separate monitoring agent.
- Critical / warn / info / ok checks for unlocked UI, missing age key, unexported keys, no recovery recipients, missing or stale instance backup, missed (overdue) schedules, password-only SSH servers, recent failures, webhooks, remote_exec tokens.
- Each row deep-links to Settings, Backups, or History.
- Refreshes about every minute from a single session-authenticated API.
Restore
restorePOST /api/history/:id/restoreGET /api/history/:id/download
Path, volume, and database restore from History. Artifacts can be local, on S3, on Bro, or on an SSH destination with key auth (pulled onto this host first).
- Path: rsync/push the backed-up tree back to the local path, SSH host, or S3 source prefix. History offers a host picker to restore onto a different server (key auth required).
- Docker volume: push/extract into a named volume on the original source or a retargeted host (SSH server or this host’s Docker socket).
- Database: pipe into psql/mysql/sqlite (native or docker exec) on the original or a retargeted host.
- .age archives decrypt automatically. Download the artifact from History without restoring in place. Password-only SSH destinations cannot pull for restore or download.
Servers & SSH keys
serversnode-sshauthType password|key
Manage VPS connections—host, port, user, credentials—then reuse them as From or To.
- Password auth works for Test connection and helpers (list volumes/containers, remote shell).
- Path transfers require an SSH key on every server endpoint involved.
- Store keys in the app, reference a system path, or attach a saved ssh_keys row.
Jobs, schedule, retention
jobscronenableVersioningenableFileRetention
Cron in the app timezone, excludes, pre-backup commands, versioned subfolders, and age-based file retention.
- 5-field cron; invalid expressions fail at schedule time. New Backup offers preset chips and VPS path / volume recipes for a first job.
- Versioning: YYYY-MM-DD_HH-mm-ss subfolders with count-based keep.
- File retention: age + min-keep for dump-style destinations (not with versioning)—local, remote SSH, S3, and Bro mailbox.
- Pre-backup commands: SSH or local shell; Bearer tokens need remote_exec to set/change them.
Validate before run
validatePOST /api/backups/:id/validatelastValidation
Dry-run connectivity and credentials without transferring data. Open a backup → Validate; the last result is stored for later.
- Probes SSH reachability / key capability, local or remote paths, S3 profile access, and database dump credentials as applicable.
- Returns pass / fail / warn checks with messages—no rsync, pack, or dump side effects.
- lastValidatedAt / lastValidationOk / lastValidationChecks persist on the config; cleared when you edit the job.
Failure webhooks
webhooksfailureWebhookUrlsuccessPingUrlbackup.failed
Optional HTTPS notification when a backup fails, plus optional success pings. Configure once under Settings → General; empty URL disables.
- Method GET / POST / PUT; URL, headers, and body support {{event}}, {{backupName}}, {{configId}}, {{historyId}}, {{errorMessage}}, {{endedAt}}.
- Failure presets: Default JSON, Discord, Telegram, Uptime Kuma push, ntfy, Slack—paste your URL and tweak the template.
- Success pings: Healthchecks-style GET (or POST) on backup.succeeded; Discord, ntfy, and Telegram presets share the same channel templates.
- Empty POST/PUT body sends the built-in backup.failed JSON. HTTPS required (http only for localhost/LAN). Send test notification to verify.
App password & passkeys
authlb_sessionWebAuthnwebauthn_credentials
Single-operator lock—no users table. Auth enables when a password hash or ≥1 passkey exists.
- App password: argon2 hash in settings; set/skip on first run.
- Passkeys: register in Settings; Sign in with passkey on /login.
- Session cookie lb_session, 30-day sliding expiry. AUTH_COOKIE_SECURE=true only behind HTTPS.
- Middleware checks the session in-process on the Node.js runtime (no HTTP self-fetch).
MCP & API tokens
mcp/mcpAuthorization: Bearerremote_execread_only
Streamable HTTP MCP on the same instance so coding agents manage backups without a local bridge.
- Create tokens under Settings → API / MCP (shown once; hashed at rest; revoke anytime).
- Tokens cannot mint tokens—CRUD requires a browser session.
- validate_backup probes endpoints without transferring (persists lastValidation). get_status returns the Status posture snapshot. Both are allowed for read_only tokens.
- remote_exec gates exec_command and changing preBackupCommands; sessions always allowed. read_only (mutually exclusive with remote_exec) may list/get, validate, and test_*; it cannot mutate. Existing tokens without it still write.
- Destructive tools (delete_*, restore_history, exec_command) require confirm=true. Audit log without secrets.