Skip to content

Actual Budget Actual Budget

Description / nameInput element
Container Registry
Container Configuration Root Path
Timezone
User ID
Group ID
Actual Budget /data Path

Build Status Last Commit OCI Pulls

Self-hosted personal finance sync server (Actual Budget) on FreeBSD.

Registry ghcr.io/daemonless/actual
Daemonless daemonless/actual
Source actualbudget/actual
Website actualbudget.org

Version Tags

Tag Description Best For
latest Upstream Binary. Built from official release. Most users — recommended.

Before deploying, ensure your host environment is ready. See the Quick Start Guide for host setup instructions, including the security model for host vs. container privileges.

Deployment

services:
  actual:
    image: "ghcr.io/daemonless/actual:latest"
    container_name: actual
    environment:
      - PUID=1000  # User ID for the application process
      - PGID=1000  # Group ID for the application process
      - TZ=UTC  # Timezone for the container
      - NODE_ENV=production  # Node runtime mode; leave as 'production'
      - ACTUAL_PORT=5006  # Internal port the sync server listens on; leave as 5006
      - ACTUAL_HOSTNAME=0.0.0.0  # Bind address for the sync server; leave as 0.0.0.0 (the app's own default, '::', is IPv6-any and breaks single-stack containers)
      - ACTUAL_DATA_DIR=/data  # Directory where Actual stores its account database, budget files and server config (under the /data volume)
    volumes:
      - "/containers/actual/data:/data"
    # always (not unless-stopped) so FreeBSD's podman rc.d auto-starts it at boot
    restart: always

Save as compose.yaml, then run podman-compose up -d.

# .env

DIRECTOR_PROJECT=actual
PUID=1000
PGID=1000
TZ=UTC
NODE_ENV=production
ACTUAL_PORT=5006
ACTUAL_HOSTNAME=0.0.0.0
ACTUAL_DATA_DIR=/data
# appjail-director.yml

options:
  - virtualnet: ':<random> default'
  - nat:
services:
  actual:
    name: actual
    options:
      - container: 'args:--pull'
    oci:
      user: root
      environment:
        - PUID: !ENV '${PUID}'
        - PGID: !ENV '${PGID}'
        - TZ: !ENV '${TZ}'
        - NODE_ENV: !ENV '${NODE_ENV}'
        - ACTUAL_PORT: !ENV '${ACTUAL_PORT}'
        - ACTUAL_HOSTNAME: !ENV '${ACTUAL_HOSTNAME}'
        - ACTUAL_DATA_DIR: !ENV '${ACTUAL_DATA_DIR}'
    volumes:
      - ACTUAL_DATA_PATH: /data
volumes:
  ACTUAL_DATA_PATH:
    device: '/containers/actual/data'
1
2
3
4
5
6
7
# Makejail

ARG tag=latest

OPTION container=boot
OPTION overwrite=force
OPTION from=ghcr.io/daemonless/actual:${tag}

Save the files above, then run appjail-director up.

Experimental

Bastille's OCI support is experimental. It requires buildah and shares the host network stack (inherit). Mount volumes with --volume HOST JAIL; without it, image-declared volumes are stored under ${bastille_volumesdir}/${jail}.

services:
  actual:
    name: actual
    image: "ghcr.io/daemonless/actual:latest"
    network:
      - mode: host
    environment:
      - PUID=1000
      - PGID=1000
      - TZ=UTC
      - NODE_ENV=production
      - ACTUAL_PORT=5006
      - ACTUAL_HOSTNAME=0.0.0.0
      - ACTUAL_DATA_DIR=/data
    volumes:
      - "/containers/actual/data:/data"

Save as bastille-compose.yml, then run bastille up.

Interactive Configuration

Parameters

Environment Variables

Variable Default Description
PUID 1000 User ID for the application process
PGID 1000 Group ID for the application process
TZ Etc/UTC Timezone for the container
NODE_ENV production Node runtime mode; leave as 'production'
ACTUAL_PORT 5006 Internal port the sync server listens on; leave as 5006
ACTUAL_HOSTNAME 0.0.0.0 Bind address for the sync server; leave as 0.0.0.0 (the app's own default, '::', is IPv6-any and breaks single-stack containers)
ACTUAL_DATA_DIR /data Directory where Actual stores its account database, budget files and server config (under the /data volume)

Volumes

Path Description
/data Application data — account database, budget files and server config

Implementation Details

  • Architectures: amd64
  • User: bsd (UID/GID set via PUID/PGID). Defaults to 1000:1000.
  • Base: Built on ghcr.io/daemonless/base (FreeBSD 15.1).

Need help? Join our Discord community.