跳轉至

Actual_Server

Actual_Server 是 Actual Budget 的自我託管伺服器元件,負責提供預算記錄、帳戶管理、交易同步以及網頁介面 API。本條目描述的部署方案是執行於 Oracle Cloud Infrastructure(OCI)免費層(Always Free)上的 Docker 容器,採用 actualbudget/actual-server:latest 映像檔。整個服務不直接對互聯網開放任何連接埠,而是接入已有的 cf_network Docker 外部網絡,由 Cloudflare Tunnel 統一代理外界連線,確保實際伺服器主機不會暴露不必要的服務表面。

Overview

Actual Budget 是一套開源、本地優先的個人理財工具。Actual_Server 是其後端,負責儲存資料庫、處理同步請求、提供網頁用戶端與 API 端點。使用 Docker Compose 部署可將環境依賴封裝,簡化升級與遷移。

本部署特色:

  • 使用 Docker Compose 3.8 語法。
  • 映像檔 actualbudget/actual-server:latest 原生支援 linux/arm64,適合 Oracle Cloud Ampere A1 Flex ARM 執行個體。
  • 容器名稱固定為 actual_server,方便與其他容器/反向代理設定互相引用。
  • 僅以 expose5006 連接埠開放予 Docker 內部網絡,不使用 ports 映射至主機,避免被外界直接掃描。
  • 資料以 Docker volume actual_data 持久化到 /data,容器更新或重建後資料仍然保留。
  • 設定時區 TZ=Asia/Hong_Kong,確保日誌時間與香港時間一致。
  • 使用外部網絡 cf_network,並指派固定 IP 172.21.0.5,讓 Cloudflare Tunnel 容器可以穩定連到 Actual_Server。

Architecture

下圖描述實際部署的邏輯架構:

Internet
   │
   ▼
Cloudflare Tunnel (cloudflared)
   │
   ▼
cf_network (外部 Docker network)
   │
   ▼
actual_server (172.21.0.5:5006)
   │
   ▼
actual_data volume (/data)

actual_server 與 Cloudflare Tunnel 容器連接在同一個 cf_network。Cloudflare Tunnel 可以透過 Docker DNS 名稱 actual_server:5006 或固定 IP 172.21.0.5:5006 向後端轉發請求。固定 IP 的另一個好處是,日後如果 Docker DNS 因容器重建而短暫失效,Tunnel 仍有明確位址可連。

actual_data 是 Docker named volume。Actual_Server 會將 SQLite 資料庫及其他設定檔寫入容器內的 /data。由於資料存放在 volume 而非容器可寫層,因此升級映像檔、重建容器或移動至另一部主機時,可以保留完整帳目記錄。

此設計亦適合與其他需要經 Cloudflare Tunnel 對外發佈的服務共用網絡,例如 litellm。共用 cf_network 後,不同容器之間以內部位址互相通訊,無需逐一開放 Oracle Cloud 防火牆連接埠。

Deployment

前置條件

  • 一部 Oracle Cloud Linux 虛擬機器。
  • 已安裝 Docker Engine 及 Docker Compose Plugin。
  • 已建立 Cloudflare Tunnel 容器,並準備好要綁定的網域名稱。
  • 已建立一個名為 cf_network 的外部 Docker 網絡。

如果 cf_network 尚未存在,可先建立:

docker network create cf_network --subnet=172.21.0.0/24

請確認 172.21.0.5 並未被其他容器佔用。若網絡已經存在,可檢查子網設定:

docker network inspect cf_network

建立部署目錄

mkdir -p ~/actual_server
cd ~/actual_server

撰寫 Docker Compose 檔案

建立 docker-compose.yml

version: '3.8'

services:
  actual_server:
    environment:
      - TZ=Asia/Hong_Kong
    image: actualbudget/actual-server:latest # 原生支援 linux/arm64,Watchtower 可無損更新
    container_name: actual_server
    restart: unless-stopped
    networks:
      cf_network:
        ipv4_address: 172.21.0.5
    expose:
      - "5006" # 僅在內部 Docker 網絡暴露,禁止使用 ports
    volumes:
      - actual_data:/data # 確保資料庫持久化

volumes:
  actual_data:

networks:
  cf_network:
    external: true # 接入已存在的 Cloudflare Tunnel 網絡

啟動服務

docker compose up -d

檢查容器狀態:

docker compose ps

預期 actual_server 狀態為 running,且沒有主機連接埠映射。與 Cloudflare Tunnel 的設定類似:

Hostname: budget.example.com
Service: http://actual_server:5006

或者直接使用固定 IP:

Service: http://172.21.0.5:5006

完成後即可透過 https://budget.example.com 進入 Actual Budget 網頁介面。

Configuration

Compose 設定說明

  • version: '3.8':Compose 檔案格式,非 Docker Engine 版本限制。
  • image: actualbudget/actual-server:latest:使用官方最新穩定映像檔。latest 標籤方便 Watchtower 自動更新;若想追求穩定,可改用指定版本標籤。
  • container_name: actual_server:固定容器名稱,讓其他容器/指令可以用 actual_server 作為主機名稱連線。
  • restart: unless-stopped:虛擬機器重新開機後,Docker 會自動啟動容器,除非管理員手動停止。
  • networks.cf_network.ipv4_address: 172.21.0.5:指派靜態內部 IP,避免容器重建後 IP 變動。
  • expose: "5006":只允許同一個 Docker 網絡內的容器存取,不會把連接埠發佈到主機網絡介面。
  • volumes: actual_data:/data:將 Actual_Server 的資料目錄掛載到持久化 volume。
  • networks.cf_network.external: true:表示 cf_network 不是由這個 Compose 檔案建立,而是預先存在。外部容器(如 cloudflared)必須加入同一網絡,才能互通。

環境變數

現階段只設定 TZ=Asia/Hong_Kong,因為 Actual_Server 預設已能在 5006 連接埠正常運作。部分版本支援以下環境變數:

  • ACTUAL_PORT:手動指定連接口,預設 5006
  • ACTUAL_HOSTNAME:綁定位址,預設 0.0.0.0
  • ACTUAL_DATA_DIR:資料儲存路徑,預設 /data
  • ACTUAL_HTTPS:是否直接啟用 HTTPS;若交由 Cloudflare Tunnel 終止 TLS,一般不設為 true

如需加入認證或更高階設定,請參考 Actual Server 官方文件,並在 environment 區段加入對應變數。

Operations

日誌查詢

docker compose logs -f actual_server

重啟

docker compose restart actual_server

手動更新

docker compose pull actual_server
docker compose up -d actual_server

如果安裝了 Watchtower,並授予其監控包含 actual_server 的容器,當 latest 映像檔有新版本時,Watchtower 會自動拉取新映像、重建容器,同時保留 actual_data volume,因此不會損失資料。

備份資料

備份前應停止容器,確保資料庫沒有寫入中的記錄:

docker compose stop actual_server

找出實際 volume 名稱:

docker volume ls

在 Compose project 目錄執行時,volume 通常會命名為 actual_server_actual_data。備份命令:

docker run --rm \
  -v actual_server_actual_data:/data \
  -v $(pwd):/backup \
  alpine tar czf /backup/actual_server_$(date +%Y%m%d).tar.gz -C /data .

完成後重新啟動:

docker compose start actual_server

還原資料

docker run --rm \
  -v actual_server_actual_data:/data \
  -v $(pwd):/backup \
  alpine tar xzf /backup/actual_server_YYYYMMDD.tar.gz -C /data

還原後重新啟動容器:

docker compose restart actual_server

FAQ

為什麼不直接用 ports 對外開放 5006?

因為 Oracle Cloud 公共 IP 會受到自動掃描及暴力嘗試。只使用 expose 配合 Cloudflare Tunnel,可以隱藏伺服器真實 IP,並加上 Cloudflare Access 等存取控制。

可以將 ipv4_address 移除嗎?

可以。若移除,容器仍然可以透過 Docker DNS 名稱 actual_server 被其他容器找到。固定 IP 的主要作用是避免重用或其他容器變更時造成影響,但並非必須。

Actual_Server 有內建登入系統嗎?

Actual_Server 本身偏向單一使用者部署。若需要多使用者或登入驗證,通常會在上層 Cloudflare Tunnel 設定 Access Policy,或使用 Basic Auth 保護入口。

如果 Oracle Cloud VM 重啟,Actual_Server 會自動啟動嗎?

會。restart: unless-stopped 令 Docker 在守護程序啟動時自動重新建立容器。前提是 Docker 服務本身已在系統開機時啟用。

為何選擇 latest 標籤而不是固定版本?

latest 適合追求快速獲得新功能的使用者。由於 actual_data 獨立於容器存在,升級風險較低。若需要高度穩定的生產環境,建議改用明確版本標籤,並先測試再升級。

Source

Coverage auto (container scan)