Skip to content

Installation

This page helps you get Actual Bench running with the simplest supported installation. Actual Bench is distributed as a Docker image, so Docker (with or without Compose) is the recommended way to run it.

  • Docker (and optionally Docker Compose) installed on the host.
  • A free host port to publish the app on. The container listens on port 3000.
  • A location for a persistent volume so Actual Bench keeps its metadata across restarts.
  • Browser access to wherever you publish Actual Bench.
  • For Direct Actual Server mode: your browser must be able to reach your Actual Server, which has CORS and cross-origin isolation requirements. See Connect to Actual Budget.
  • For HTTP API Server mode: the Actual Bench container must be able to reach your actual-http-api server.

Actual Bench publishes multi-architecture images (linux/amd64 and linux/arm64):

Tag Stability Use it when
latest Stable Normal production / self-hosting (default)
:<version> (e.g. :1.2.4) Stable, pinned You want a specific, unchanging version
edge Unstable — rebuilt on every merge Testing the newest changes before a release

Create a docker-compose.yml:

services:
actual-bench:
image: xrous/actual-bench:latest
container_name: actual-bench
ports:
- "3000:3000"
environment:
ACTUAL_BENCH_DB_PATH: /data/actual-bench.sqlite
# --- Optional settings (uncomment to use; see the Configuration guide) ---
# DIRECT_BROWSER_API: "0" # offer only HTTP API Server mode
# LOG_LEVEL: info # debug | info | warn | error
# SYNC_VAULT_KEY: "<strong-secret>" # enable unattended server-side sync
# SYNC_SCHEDULER_SECRET: "<strong-secret>" # enable the external scheduler trigger
volumes:
- actual-bench-data:/data
restart: unless-stopped
volumes:
actual-bench-data:

Start it:

Terminal window
docker compose up -d

No environment variables are required for a basic setup — ACTUAL_BENCH_DB_PATH is shown here only to make the metadata location explicit; it already defaults to /data/actual-bench.sqlite. The commented lines are optional settings you can provide; see Configuration for what each one does.

The equivalent without Compose:

Terminal window
docker run -d \
--name actual-bench \
--restart unless-stopped \
-p 3000:3000 \
-v actual-bench-data:/data \
xrous/actual-bench:latest

Open the app in your browser:

  • Local host: http://localhost:3000
  • Remote host: http://<your-server>:3000, or your reverse-proxy URL

You should land on the connection screen. Setting up the connection is covered in Connect to Actual Budget.

  1. The app loads and shows the connection screen.
  2. The version appears in the sidebar footer (for example v1.2.4).
  3. Open App Health (under Tools) and confirm:
    • Writable is Yes.
    • Schema shows a version number (not Not initialized).
    • Persistence reads Persistent when /data is mounted.

If Writable is No or persistence looks wrong, re-check the /data volume mount and its permissions before connecting.

Actual Bench stores its own workflow metadata in a SQLite database at /data/actual-bench.sqlite (set ACTUAL_BENCH_DB_PATH to change the path). Persist and back up the /data volume to keep this data across container recreation.

To move to a newer image:

Terminal window
docker compose pull
docker compose up -d

For a safe upgrade — including backups, version pinning, and database migration notes — follow the Upgrading and Backups guide.

Continue to Connect to Actual Budget.