Skip to content

Configuration Reference

Server Environment Variables

Variable Default Required Description
DATABASE_URL — Yes PostgreSQL connection string (e.g. postgres://user:pass@host/db).
ASSIMILATE_SECRET_KEY — Yes Secret used to derive the AES-256-GCM encryption key for repository passphrases.
ASSIMILATE_BIND_ADDR 0.0.0.0:8080 No TCP address and port the server listens on.
ASSIMILATE_STATIC_DIR ./static No Directory containing the compiled Vue SPA. If absent, the static file route is disabled.
ASSIMILATE_DOCS_DIR ./docs_html No Directory containing the built MkDocs site served at /docs. If absent, the /docs route is disabled.
SSH_AUTH_SOCK — No Path to the SSH agent socket on the server. Required for SSH agent forwarding and borg repository initialisation.
SSH_KEY_DIR /app/ssh No Directory where the server stores its managed Ed25519 key pair (id_ed25519 / id_ed25519.pub).
BORG_BINARY borg No Path to the borg executable used by the server for repository operations (init, archive listing, extraction).
ASSIMILATE_DB_MAX_CONN 20 No Maximum number of connections in the PostgreSQL connection pool.
ASSIMILATE_BORG_QUERY_TIMEOUT_SECS 300 No Maximum time a single borg list/borg info query may run before it is killed and the operation fails. Bounds hangs (e.g. an unreachable repository) so an import never gets stuck at "Listing archives". Increase for very large repositories over slow links.
ASSIMILATE_BORG_LIST_STAGE_TIMEOUT_SECS 1800 No Upper bound on the total time an archive-listing stage may spend retrying borg list while the repository is locked by another operation (e.g. a running backup). Without this, lock-wait retries could keep an import stuck at "Listing archives" for up to 90 minutes.
ASSIMILATE_SECURE_COOKIES true No When true (default), session cookies are set with the Secure flag (requires HTTPS) and responses carry a Strict-Transport-Security header. Set to false for local development without TLS.
AGENT_BINARY_DIR — No Directory containing arch-specific agent binaries (agent-x86_64, agent-aarch64, etc.) used by the SSH deploy feature. If unset, the server looks in /app/ (Docker) or alongside its own executable.
VAPID_PUBLIC_KEY — No Web Push VAPID public key. Used as a fallback for browser push notifications when no key is stored in system settings. See Notifications.
VAPID_PRIVATE_KEY — No Web Push VAPID private key. Fallback companion to VAPID_PUBLIC_KEY; keys stored via the API take precedence.
ASSIMILATE_TRUSTED_PROXIES — No Comma-separated list of trusted proxy CIDR networks (e.g., 10.0.0.0/8,172.16.0.0/12). When set, the server respects the X-Forwarded-For header from these proxies to determine the real client IP for rate limiting. Leave empty to never trust X-Forwarded-For.

Security

ASSIMILATE_SECRET_KEY is used to derive the encryption key that protects all repository passphrases stored in the database. If you lose or rotate this value, every encrypted passphrase becomes permanently unrecoverable. Store it in a secrets manager and never change it after initial setup.

Agent Environment Variables

Variable / Flag Default Required Description
BORG_SERVER_URL / --server-url — Yes WebSocket URL of the Assimilate server (e.g. ws://server:8080 or wss://server). http:// and https:// prefixes are automatically converted to ws:// / wss://.
BORG_AGENT_TOKEN / --token — Yes Agent authentication token generated by the server when a host is created.
BORG_BINARY borg No Path to the borg executable on the agent machine.

System Settings

System settings are stored in the database and managed through the UI or the /api/system/settings endpoint.

System Settings System Settings (Database storage)

Setting Default Description
retention_days 7 Legacy setting — number of days to retain backup-run history (failed/cancelled runs without an archive) and system event log entries. Replaced by the independent settings below on first save, but still read as a fallback.
report_retention_days retention_days (or 0) Days to keep successful/archived backup reports. Reports with an archive are pruned by this window. 0 = keep forever.
failed_report_retention_days 365 Days to keep failed/archive-less backup reports. 0 = keep forever. To clear an agent's failed reports immediately rather than waiting on this window, use Clean up failed backups in its header overflow menu.
system_event_retention_days retention_days (or 90) Days to keep system event log entries. 0 = keep forever.
notification_delivery_retention_days retention_days (or 30) Days to keep notification delivery-attempt history (the notification_deliveries debug/retry log). 0 = keep forever.
run_event_retention_days retention_days (or 90) Days to keep a run's power-management event timeline (the backup_run_events table). 0 = keep forever.
timezone UTC Timezone used for displaying timestamps in the UI and for scheduling cron-based backups (e.g., Europe/Berlin, America/New_York).
session_idle_timeout_minutes 480 Number of minutes of inactivity before a session is automatically revoked. Must be a positive integer; the idle timeout cannot currently be disabled. Does not apply to "Remember Me" sessions, which are bounded only by their 7-day absolute expiry.
public_url unset Base URL (scheme + host, e.g. https://backups.example.com) used to build absolute deep links -- such as an Activity Log link on a failed or warning backup -- in email and webhook notifications. Must use http or https and must be a bare origin -- no path, query, fragment, or embedded credentials (rejected, not stripped). The stored value is normalized to scheme://host[:port] (trailing slash and surrounding whitespace removed). Unset by default, in which case those notifications omit the link. Web Push notifications don't need this setting: the browser resolves their links against its own origin. There is no dedicated field in the Settings UI yet -- set it via PUT /api/system/settings (see Notifications).

Database Storage

Open System → Database Storage to inspect PostgreSQL disk allocation. The table lists every application table in descending size order and separates table data, indexes, and TOAST data. Use this view to identify growth in archive indexes, backup reports, audit records, and other persisted data.

The total includes PostgreSQL system catalogs and database overhead. The Other PostgreSQL storage row accounts for allocation not owned by an application table. Deleted rows remain reusable inside PostgreSQL and do not necessarily reduce the database files on disk.

Config Export / Import

The server provides GET /api/config/export and POST /api/config/import endpoints for portable JSON snapshots of the server configuration. This is useful for migrating between servers or creating backups of the configuration.

Exported Entities

Entity Included Notes
Hosts Connection details, display name, domain, default backup paths, exclude patterns, pre/post-backup commands, file change patterns, hostname patterns Agent authentication tokens are not exported; imported hosts receive a placeholder token. Import matches existing hosts by hostname and domain, so two hosts sharing a hostname import as distinct agents.
Schedules Name, cron expression, enabled state, retention settings, backup sources, targets, exclude patterns, per-agent overrides Only schedules with at least one valid target are imported.
Repositories SSH connection details, compression, encryption mode, enabled state, sync schedule, SSH host key (of the repository's host, applied to every repository on it when imported), quota (warn/critical thresholds and actions), tags Passphrases are never exported (see below).

Repository Passphrase Handling

Repository passphrases are encrypted at rest with a server-specific AES-256-GCM key and are never included in the export. After importing a config containing repositories, each repo's passphrase must be set manually before the scheduler can sync with it:

  1. Navigate to Repositories in the UI.
  2. Open each imported repository's detail page.
  3. Set the passphrase using the repository edit form.

Until a passphrase is set, the imported repository is marked as importing and the scheduler will skip it.

Sync Schedule Preservation

A repository's sync schedule (the cron expression for automatic repository synchronisation) is exported verbatim. When the exported value is null (no schedule configured), the import preserves that — the repository will not have an automatic sync schedule. This differs from creating a new repository through the UI, which uses a system default schedule.

Importing a config onto an existing repository with the same name updates the sync schedule to match the export, including clearing it if the export has null.

Usage

# Export current config
curl -s -X GET http://localhost:8080/api/config/export \
  -H "cookie: session=<admin-session>" | jq . > config.json

# Import a config (destructive merge — creates and updates entities)
curl -s -X POST http://localhost:8080/api/config/import \
  -H "cookie: session=<admin-session>" \
  -H "content-type: application/json" \
  -d @config.json

The import is additive and idempotent:

  • Entities matching by name are updated in place.
  • New entities are created.
  • No entities are deleted (the import never removes existing hosts, schedules, or repositories not present in the payload).

Schedule Configuration

Each schedule is associated with a repository and controls when and how backups run. Managed via the Scheduling UI or the /api/schedules endpoint.

Field Description
schedule_type Operation type: backup, check, or verify.
cron_expression Standard 5-field cron expression defining when the schedule fires (e.g. 0 2 * * *).
enabled Whether the schedule is active.
keep_daily Number of daily archives to retain during pruning.
keep_weekly Number of weekly archives to retain during pruning.
keep_monthly Number of monthly archives to retain during pruning.
keep_yearly Number of yearly archives to retain during pruning.
compact_enabled Whether to run borg compact after pruning to reclaim freed space.
backup_sources List of filesystem paths to include in the backup.
exclude_patterns List of borg exclude patterns applied to this schedule.
ignore_global_excludes When true, global exclude patterns (configured under Excludes) are not applied to this schedule.
canary_enabled When true, a canary file is written before backup and verified after to detect silent failures.
vm_snapshot_enabled When true, the libvirt/QEMU domains of every host this schedule targets are staged before the backup starts, using each host's own settings. Hosts that do not allow it are skipped. See VM Snapshots.
pre_backup_commands List of hook commands executed on the agent before the backup starts. Each entry is an object {"command": "...", "timeout_seconds": null}: the command is run as its own sh -c invocation and may span multiple lines (a full script, not just one statement), and timeout_seconds overrides hook_timeout_seconds for that command alone — null inherits it. Between 1 and 86400 (24 hours) where set. A bare string is still accepted in place of an object and read as a command with no timeout of its own, so older API clients and exported configs keep working. If any entry fails, the backup is aborted and post_backup_commands is not run.
post_backup_commands Same shape as pre_backup_commands, executed on the agent after the backup completes with success or warnings. Not run if borg create fails outright.
hook_timeout_seconds Default timeout, in seconds, for every pre- and post-backup command that does not set its own timeout_seconds. A command still running past its timeout is killed and treated as a failure. Defaults to 60, up to a maximum of 3600.
missed_backup_threshold Number of consecutive missed backups (agent or target unreachable at trigger time) tolerated before the schedule is marked failed and automatically disabled — see Agent status and auto-disable. Below this count, a miss only shows as a warning. Defaults to 3.
catch_up_min_lead_minutes Minimum time, in minutes, that must remain before the next scheduled run for a catch-up to still start. A host coming back closer than this to the next run has its pending miss dropped instead, so the catch-up never collides with the regular run. Between 1 and 10080 (7 days). Defaults to 120. The schedule's only catch-up setting — whether a host is waited for at all is set on the agent or repository.

Repository Configuration

Repositories are managed via the Repositories UI or the /api/repos endpoint.

Field Description
name Human-readable label for the repository.
ssh_host Hostname or IP of the borg repository server.
ssh_user SSH username used to connect to the repository server.
ssh_port SSH port on the repository server (typically 22).
repo_path Absolute path to the borg repository on the remote host (e.g. /backup/repos/myhost).
encryption Borg encryption mode: repokey, repokey-blake2, keyfile, keyfile-blake2, authenticated, authenticated-blake2, or none.
compression Compression algorithm: none, lz4, zstd,<level>, or zlib,<level>.
passphrase Repository passphrase. Stored encrypted at rest using AES-256-GCM. See Security.
enabled Whether the repository is active. Disabled repositories are skipped by the scheduler.

Security Configuration

These values are compiled into the server and are not runtime-configurable without a code change.

Parameter Value Description
Login rate limit (per-username, per-IP) 5 attempts per 15 minutes Scoped to a single (username, IP) pair; rotating usernames from the same IP is not caught by this limiter alone. Returns 429 when exceeded.
Login rate limit (per-IP) 30 attempts per minute IP-address-scoped, independent of username. Applies to /api/auth/login and the TOTP login-step endpoints. Returns 429 when exceeded.
Account lockout threshold 10 consecutive failed attempts since last successful login Number of failed attempts (across all IPs) before the account is temporarily locked. Returns 401 (same as invalid credentials) to prevent enumeration.
Lockout duration (exponential backoff) 1 min → 5 min → 15 min → 1 hr → 24 hr Escalating lockout durations based on consecutive lockout cycles. Resets on successful login.
Login attempt record retention 90 days Failed/successful login attempt records (used for the rate limit and lockout checks above) older than this are pruned by the scheduler's retention cleanup.
API rate limit (per-user) 60 requests per 60 seconds Sliding-window rate limit applied to mutating (POST/PUT/PATCH/DELETE) requests on authenticated routes; reads (GET/HEAD/OPTIONS) are not throttled. Returns 429 when exceeded.
Session cookie HttpOnly; SameSite=Lax; Path=/; Max-Age=86400 Session cookie attributes. Sessions expire after 24 hours (7 days with remember-me).
Password minimum length 8 characters Minimum length enforced when setting or changing a password.
Token hashing SHA-256 API tokens are stored as SHA-256 hashes; the plaintext is never persisted.
Passphrase encryption AES-256-GCM Repository passphrases are encrypted with a key derived from ASSIMILATE_SECRET_KEY.
Session idle timeout 480 minutes (8 hours) Inactive sessions are automatically revoked after this duration. Configurable via System Settings.
TOTP/2FA SHA-1, 30-second period, 6-digit codes Two-factor authentication using time-based one-time passwords. Enrolled per user from the Profile page. Recovery codes (bcrypt-hashed) are provided at enrollment.

Two-Factor Authentication (TOTP)

Users can enable TOTP-based two-factor authentication from their Profile page. Once enabled:

  1. Login requires password + TOTP code in two steps.
  2. The password step returns a temporary session token (valid for 10 minutes) that can only be used to complete TOTP verification.
  3. Recovery codes (10 codes, provided at enrollment) can bypass TOTP if the authenticator device is lost. Each recovery code can be used once.
  4. To disable TOTP, the current password must be provided.

Session Management

Users can view and manage their active sessions from the Sessions tab in their Profile page:

  • Each session shows its creation time, expiration, last activity, and whether "Remember Me" is enabled.
  • Users can revoke individual sessions (except the current one).
  • An Idle Timeout can be configured in System Settings. Sessions with no activity beyond this threshold are automatically revoked.

See Security for a full discussion of the security model.