Skip to content

Getting Started

This guide walks you through installing and running Assimilate for the first time, from prerequisites to your first completed backup.

Using Pre-built Docker Images

The fastest way to get started. Pre-built images for the server and agent are published to the GitHub Container Registry on every release and nightly from main:

Image Tags
ghcr.io/alexmohr/assimilate latest, semver (1.2.3, 1.2, 1), nightly, sha-<commit>
ghcr.io/alexmohr/assimilate-agent latest, semver (1.2.3, 1.2, 1), nightly, sha-<commit>

Tip

Use nightly for the latest development build from main, or pin to a release tag for stability.

Server: docker-compose.yml (pre-built images)

Deploy this on the machine hosting the Assimilate server:

services:
  postgres:
    image: postgres:latest
    environment:
      POSTGRES_DB: borg
      POSTGRES_USER: borg
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-borg_secret}
    volumes:
      - pgdata:/var/lib/postgresql
    ports:
      - "5432:5432"
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U borg -d borg"]
      interval: 5s
      timeout: 3s
      retries: 5

  server:
    image: ghcr.io/alexmohr/assimilate:latest
    ports:
      - "8080:8080"
    environment:
      DATABASE_URL: postgres://borg:${POSTGRES_PASSWORD:-borg_secret}@postgres:5432/borg
      ASSIMILATE_SECRET_KEY: ${ASSIMILATE_SECRET_KEY:?ASSIMILATE_SECRET_KEY must be set}
      ASSIMILATE_BIND_ADDR: "0.0.0.0:8080"
      ASSIMILATE_STATIC_DIR: /app/static
    volumes:
      - ssh_keys:/app/ssh
    depends_on:
      postgres:
        condition: service_healthy

volumes:
  pgdata:
  ssh_keys:

Agent: docker-compose.yml (pre-built images)

Deploy this on each machine you want to back up — not on the server:

services:
  agent:
    image: ghcr.io/alexmohr/assimilate-agent:latest
    environment:
      BORG_SERVER_URL: http://<server-address>:8080
      BORG_AGENT_TOKEN: ${BORG_AGENT_TOKEN:?BORG_AGENT_TOKEN must be set}

Running with pre-built images

On the server machine:

export ASSIMILATE_SECRET_KEY=$(openssl rand -hex 32)
docker compose up -d

Once the server is running, create an agent in the UI and copy its token.

On each backup machine:

export BORG_AGENT_TOKEN=<token from server UI>
docker compose up -d

Docker Compose Quickstart (build from source)

Environment variables

Variable Required Default Description
ASSIMILATE_SECRET_KEY Yes — 32-byte hex key used to encrypt repository passphrases at rest (AES-256-GCM)
POSTGRES_PASSWORD No borg_secret Password for the PostgreSQL borg user
BORG_AGENT_TOKEN Agent only — Token copied from the server UI after creating an agent

Protect ASSIMILATE_SECRET_KEY

This key derives the AES-256-GCM 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 or a secure .env file that is never committed to version control.

Server: docker-compose.yml

The repository ships the server compose file at its root — use that rather than a copy, so it cannot drift from the images and health checks the project actually tests. Its server service builds from source (build: { context: ., dockerfile: Dockerfile.server }) rather than pulling a published image, so run it from inside a clone; the file on its own is not enough:

git clone https://github.com/alexmohr/assimilate.git
cd assimilate

It brings up PostgreSQL and the server together, waits for the database to pass its health check before starting the server, and keeps the generated SSH keys in a named volume. The only values you need to supply are the two environment variables in the table above — put them in a .env file beside the compose file and see First run below. The server listens on 8080; to move it, override ASSIMILATE_BIND_ADDR and the published port.

Agent: docker-compose.yml

Deploy this on each machine you want to back up — not on the server:

services:
  agent:
    build:
      context: .
      dockerfile: Dockerfile.agent
    environment:
      BORG_SERVER_URL: http://<server-address>:8080
      BORG_AGENT_TOKEN: ${BORG_AGENT_TOKEN:?BORG_AGENT_TOKEN must be set}

First run

Generate a secret key and start the server:

export ASSIMILATE_SECRET_KEY=$(openssl rand -hex 32)
docker compose up -d

The server creates a default admin account and generates an Ed25519 SSH key pair on first start. The SSH key pair is persisted in the ssh_keys volume and the public key is visible under System in the admin UI.

Once the server is running, create an agent in the UI and copy its token. Then on each backup machine:

export BORG_AGENT_TOKEN=<token from server UI>
docker compose up -d

Manual Build

Prerequisites

Install the following before proceeding:

  • Rust nightly — install via rustup: rustup toolchain install nightly
  • Node.js 20+ — required to build the frontend
  • PostgreSQL — the server stores all state in a PostgreSQL database
  • BorgBackup — must be installed on every machine running the agent

Tip

The Devcontainer Setup section provides a fully self-contained environment with all dependencies pre-installed — recommended for contributors and evaluation.

Build the server and agent binaries:

cargo build --workspace

Build the frontend and place the output where the server can serve it:

cd frontend && npm install && npm run build

The server looks for static files in the directory specified by ASSIMILATE_STATIC_DIR (default: ./static). Copy the built frontend there:

cp -r frontend/dist/* static/

Start the server:

export DATABASE_URL=postgres://borg:borg_secret@localhost:5432/borg
export ASSIMILATE_SECRET_KEY=$(openssl rand -hex 32)
cargo run -p server

Start the agent on each backup machine (after creating a host in the UI):

export BORG_SERVER_URL=http://<server-address>:8080
export BORG_AGENT_TOKEN=<token from server UI>
cargo run -p agent

The agent accepts http://, https://, ws://, or wss:// URLs — it normalises them automatically.

See Configuration for the full list of server environment variables.

First Login

Open http://localhost:8080 in your browser.

Login

Change the default password immediately

The server creates a default admin account with credentials admin / admin. You are required to change the password on first login. Do not skip this step on any internet-facing deployment.

After changing the password, the dashboard loads and shows no agents yet.

Dashboard

Adding Your First Agent

An agent represents a machine running the Assimilate agent binary.

  1. Navigate to Agents and click New agent.
  2. Enter a display name for the machine.
  3. Click Save — the server generates a unique agent token.
  4. Copy the token shown on the agent detail page.
  5. On the backup machine, start the agent with that token:
BORG_SERVER_URL=http://<server-address>:8080 \
BORG_AGENT_TOKEN=<copied-token> \
./assimilate-agent

The agent status changes to Online in the dashboard once the agent connects.

See Agent Management for systemd unit examples and advanced options.

Adding Your First Repository

A repository is a Borg backup repository, typically accessed over SSH.

SSH key setup

The server holds an Ed25519 key pair used to authenticate to borg repository hosts. Retrieve the public key from System in the admin UI, then add it to ~/.ssh/authorized_keys on the repository host:

# On the repository host:
echo "<public key from System page>" >> ~/.ssh/authorized_keys

Tip

Use SSH Agent Forwarding so agent machines authenticate using the server's key — no SSH keys need to be distributed to agent machines.

Create the repository

  1. Navigate to Repos and click New repository.
  2. Fill in the connection details:

    Field Example
    SSH Host backup.example.com
    SSH User borg
    SSH Port 22
    Repo Path /backup/repos/myhost
    Passphrase a strong random passphrase
  3. Click Test Connection to verify SSH access.

  4. Click Initialize to run borg init and create the repository.

See Repository Management for pruning policies and passphrase rotation.

Your First Backup

  1. Navigate to Scheduling and click Add Schedule.
  2. Select the agent and repository created above.
  3. Set the paths to back up (e.g., /home, /etc).
  4. Choose a cron expression or interval (e.g., 0 2 * * * for 2 AM daily).
  5. Click Save.
  6. Click Run now to trigger an immediate backup.

The dashboard shows the backup progress in real time. Once complete, the archive appears under Archives for the repository.

See Scheduling & Retention for retention policies and pre/post hooks.

Devcontainer Setup

The project includes a devcontainer for contributors. It provides a fully self-contained environment — no local PostgreSQL, SSH keys, or borg installation required.

Services

Service Purpose
dev Rust nightly + Node.js + borg — your workspace
postgres PostgreSQL database
borg-repo SSH server + borg acting as the repository target

Start the environment

Open the project in VS Code and select Reopen in Container (or run Dev Containers: Reopen in Container from the command palette).

On first start, an SSH key pair is generated and shared with the borg-repo container automatically.

Start the server and Vite dev server with a single command:

.devcontainer/start.sh

After creating an agent in the UI and copying its token, start the agent binary:

source /tmp/ssh-agent-env.sh
BORG_SERVER_URL=http://localhost:8080 BORG_AGENT_TOKEN=<token> cargo run -p agent

When creating a repository in the devcontainer, use these settings:

Field Value
SSH Host localhost or borg-repo
SSH User borg
SSH Port 22
Repo Path /backup/repos/<name>
Passphrase any value (e.g. devpass)

Tip

Without a devcontainer, start PostgreSQL manually and set DATABASE_URL and ASSIMILATE_SECRET_KEY before running cargo run -p server. Run cd frontend && npm run dev in a separate terminal for hot-reload.