mono-actual-sync Svelte Themes

Mono Actual Sync

A self-hosted web UI bridging Monobank transactions to Actual Budget via Docker & CasaOS.

Monobank → Actual Budget Sync

Self-hosted web UI that syncs transactions from Monobank into an Actual Budget server.

The goal is “start it, open the UI, configure, sync” — no env-var juggling required for normal use.

Quickstart (Standard Docker)

The easiest way to run the app is using the pre-built Docker image from the GitHub Container Registry. (If you are using CasaOS, skip to the CasaOS section below).

1) Prerequisites

  • Docker with docker compose
  • An Actual Budget server you can reach from this container (URL + password + Budget Sync ID)
  • A Monobank Personal Token

2) Start the app

Create a docker-compose.yml file:

services:
  mono-actual-sync:
    image: ghcr.io/sviatcraft/mono-actual-sync:latest
    container_name: mono-actual-sync
    ports:
      - "9191:9191"
    environment:
      PORT: "9191"
      # Set your timezone so imported transaction dates match your local day boundary.
      TZ: "Europe/Kyiv"
    volumes:
      # Standard Docker named volume
      - mono_actual_sync_data:/app/backend/data
    restart: unless-stopped

volumes:
  mono_actual_sync_data:

Run the following command in the same directory:

docker compose up -d

Open http://localhost:9191 (or your server's IP if you changed the port mapping).


CasaOS Installation

This app supports native CasaOS integration. The easiest way to install it is to import the custom configuration below, which automatically handles the app icon, web UI routing, and saves your configuration directly to your CasaOS AppData folder.

Installation Steps:

  1. Open your CasaOS Dashboard.
  2. Click the + icon and select Install a customized app.
  3. Click the Import button in the top right.
  4. Paste the following code into the import window:
services:
  mono-actual-sync:
    image: ghcr.io/sviatcraft/mono-actual-sync:latest
    container_name: mono-actual-sync
    ports:
      - "9191:9191"
    environment:
      PORT: "9191"
      TZ: "Europe/Kyiv"
    volumes:
      # CasaOS-specific bind mount for easy file access in the Files app
      - /DATA/AppData/mono-actual-sync:/app/backend/data
    restart: unless-stopped

# --- CasaOS App Store Metadata ---
x-casaos:
  architectures:
    - amd64
    - arm64
  main: "mono-actual-sync"
  description:
    en_us: "Self-hosted web UI that syncs transactions from Monobank into an Actual Budget server. Set it up once, map your accounts, and easily keep your budget up to date with manual or hourly background syncs."
  tagline:
    en_us: "Bridge Monobank to Actual Budget"
  developer: "sviatcraft"
  author: "sviatcraft"
  icon: "https://raw.githubusercontent.com/sviatcraft/mono-actual-sync/main/frontend/public/favicon.svg" 
  thumbnail: ""
  title:
    en_us: "Mono Actual Sync"
  category: "Finance"
  port_map: "9191"
  index: "/"
  tips:
    before_install:
      en_us: "You will need your Monobank Personal Token and an existing Actual Budget server (URL, Password, and Sync ID) to configure this app after installation."
  1. Click Submit, ensure the visual fields are populated, and then click Install.

Configuration in the UI

Once the app is running, open the web UI:

  • Paste your Monobank token.
  • Enter Actual Server URL, Server Password, and Budget Sync ID.
  • Fetch accounts, then map Monobank accounts/cards/jars → Actual accounts.
  • Click Sync now (optionally enable hourly background sync).

Important security note (read before exposing)

  • There is currently no login / authentication for /api/*.
  • The default configuration binds to 0.0.0.0:9191, making the UI/API reachable from your LAN.
  • Anyone on the same network who can reach the service can read decrypted config (including tokens) and trigger syncs. Do not expose this port to the public internet.
  • To restrict access to localhost only, change the port mapping to "127.0.0.1:9191:9191".

Data persistence + encryption (automatic)

  • Configuration is saved to the /data folder (encrypted at rest).
  • The encryption key is stored alongside it in .encryption_key.
  • CasaOS Users: You can easily back up these files by opening the CasaOS Files app and navigating to AppData/mono-actual-sync.
  • Backup tip: back up config.json and .encryption_key together — losing the key means the config can’t be decrypted.

Common setup gotcha: Actual server URL from Docker

The Actual Server URL must be reachable from inside the container.

  • If Actual runs on another machine: use that machine’s LAN IP/hostname + port.
  • If Actual runs on the same computer:
    • macOS/Windows Docker Desktop usually supports http://host.docker.internal:<port>
    • Linux (including CasaOS) generally requires using your host’s LAN IP (e.g., http://192.168.1.X:5006).

Features

  • Web UI to configure credentials, mapping, and automation
  • Manual “Sync now”
  • Optional hourly background sync (node-cron)
  • Basic protection against Monobank rate limits (60s cooldown between Monobank calls)

Advanced: Building from Source

If you prefer to build the Docker image locally instead of using the pre-built registry image:

git clone [https://github.com/sviatcraft/mono-actual-sync.git](https://github.com/sviatcraft/mono-actual-sync.git)
cd mono-actual-sync
docker compose -f docker-compose.dev.yml up --build -d

(Requires creating a local docker-compose.dev.yml that uses build: . instead of the image key).

Advanced: local development (two processes)

Prereqs: Node.js 18+ and npm.

1) Backend

cd backend
npm install
npm run dev

2) Frontend

cd frontend
npm install
npm run dev

Open the Vite dev server URL (usually http://localhost:5173). In dev, Vite proxies /apihttp://localhost:9191 (see frontend/vite.config.js).


Backend API (for debugging)

Endpoints (all under /api):

  • GET /api/config – returns decrypted config (or defaults)
  • POST /api/config – saves config (encrypted) and (re)starts cron depending on useNodeCron
  • POST /api/fetch-accounts – verifies credentials, fetches account lists, persists accountCache
  • POST /api/sync – starts a sync using the saved config
  • GET /api/sync-status – returns { isSyncing: boolean }

Rate limiting:

  • Enforces a 60s cooldown between Monobank calls (returns 429 with a waitTime).

Troubleshooting

  • “Rate limit active”: Monobank calls are gated to 1 request per 60 seconds. Wait for the cooldown.
  • Actual connection errors: Double-check Actual Server URL, Budget Sync ID, and Server Password. Remember to use your server's LAN IP if running on Linux/CasaOS.
  • “Invalid Personal Token”: Recreate or re-copy the Monobank Personal Token.

Status / roadmap

  • Publish pre-built Docker image to GHCR.
  • Add x-casaos metadata for true 1-click CasaOS App Store integration.
  • Add optional app-level authentication for /api/* (e.g. APP_TOKEN / Basic Auth)

Top categories

Loading Svelte Themes