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,方便與其他容器/反向代理設定互相引用。 - 僅以
expose將5006連接埠開放予 Docker 內部網絡,不使用ports映射至主機,避免被外界直接掃描。 - 資料以 Docker volume
actual_data持久化到/data,容器更新或重建後資料仍然保留。 - 設定時區
TZ=Asia/Hong_Kong,確保日誌時間與香港時間一致。 - 使用外部網絡
cf_network,並指派固定 IP172.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 獨立於容器存在,升級風險較低。若需要高度穩定的生產環境,建議改用明確版本標籤,並先測試再升級。
Related Links¶
- docker
- cloudflare-tunnel
- oracle-cloud
- litellm
- Watchtower
- actual-budget
Source¶
Coverage auto (container scan)