OpenLogs

All tools

Wealthfolio

Local-first tracker for investments, net worth and spending.

Replaces

Paid investment tracking services, such as Empower.

All open-source alternatives to Empower

Difficulty

Difficulty: Easy

1 service, 1 volume mount, no env values to set, no elevated host access. Heuristic score 0 of 11: easy.

Stack

Rust (language)

Deployment

docker_compose

Requirements

Not stated.

License

AGPL-3.0 (OSI-approved open source)

Read from github.com/wealthfolio/wealthfolio/blob/1e08bbc/LICENSE

Business model

Unknown

The README at the pinned commit does not state a business model, so it stays unknown.

Source: github.com/wealthfolio/wealthfolio/blob/1e08bbc/README.md, read on .

Repository

wealthfolio/wealthfolio

GitHub stats

Stars
9,231
Forks
768
Open issues and pull requests
534
Last push
2026-10-22
Latest release
v3.10.0
Released
2026-10-14

From the GitHub API on . These numbers are a snapshot, not live. GitHub detected the license as AGPL-3.0.

Compose file

Config check passed docker compose config exited 0 on this exact file on 2026-10-22.
compose.yml Version 1
# Wealthfolio - Production Docker Compose
#
# Usage: docker compose --env-file .env.docker up -d
# Reverse proxy overlay: docker compose --env-file .env.docker -f compose.yml -f compose.proxy.yml up -d
# Dev overlay: docker compose --env-file .env.docker -f compose.yml -f compose.dev.yml up
#
# Publishes port 8088 for direct browser access.

services:
  wealthfolio:
    image: wealthfolio/wealthfolio:latest
    container_name: wealthfolio
    restart: unless-stopped
    ports:
      - "${WF_PORT:-8088}:8088"
    volumes:
      - wealthfolio-data:/data
    environment:
      WF_LISTEN_ADDR: "0.0.0.0:8088"
      # Optional installation root; empty uses the database's parent directory.
      WF_DATA_DIR: "${WF_DATA_DIR:-}"
      # Preserve the legacy filename by default and honor an explicitly empty path.
      WF_DB_PATH: "${WF_DB_PATH-/data/wealthfolio.db}"
      # Required — generate with: openssl rand -base64 32
      WF_SECRET_KEY: "${WF_SECRET_KEY:-}"
      # Alternative: path inside the container to a separately mounted secret.
      WF_SECRET_KEY_FILE: "${WF_SECRET_KEY_FILE:-}"
      # Startup requirement; convert existing databases offline before enabling.
      WF_DB_REQUIRE_ENCRYPTION: "${WF_DB_REQUIRE_ENCRYPTION:-0}"

      # ── Authentication ────────────────────────────────────────────────
      # Required when listening on 0.0.0.0 (the default for Docker).
      # Provide an Argon2id PHC hash of your password.
      #
      # IMPORTANT — Docker Compose interpolates "$" in .env files and YAML:
      #   .env file  → WF_AUTH_PASSWORD_HASH='$argon2id$v=19$...'  (single quotes)
      #   .env file  → WF_AUTH_PASSWORD_HASH=$$argon2id$$v=19$$...  (double every $)
      #   YAML inline → WF_AUTH_PASSWORD_HASH: '$$argon2id$$v=19$$...'  (double every $)
      #
      # Generate a hash:
      #   printf 'your-password' | argon2 yoursalt16chars! -id -e
      #
      # If a reverse proxy handles auth instead, set WF_AUTH_REQUIRED: "false"
      # and leave WF_AUTH_PASSWORD_HASH empty.
      WF_AUTH_PASSWORD_HASH: "${WF_AUTH_PASSWORD_HASH:-}"
      WF_AUTH_TOKEN_TTL_MINUTES: "${WF_AUTH_TOKEN_TTL_MINUTES:-60}"
      # Set to "false" to skip the auth requirement (e.g. reverse proxy handles auth)
      # WF_AUTH_REQUIRED: "true"

      # ── OIDC / SSO (optional) ─────────────────────────────────────────
      # Sign in via any OpenID Connect provider (Authentik, PocketID, Authelia, …).
      # Works alongside or instead of WF_AUTH_PASSWORD_HASH; enabled when both the
      # issuer URL and client id are set. Redirect URL must be registered in the IdP.
      WF_OIDC_ISSUER_URL: "${WF_OIDC_ISSUER_URL:-}"
      WF_OIDC_CLIENT_ID: "${WF_OIDC_CLIENT_ID:-}"
      WF_OIDC_CLIENT_SECRET: "${WF_OIDC_CLIENT_SECRET:-}"
      WF_OIDC_REDIRECT_URL: "${WF_OIDC_REDIRECT_URL:-}"
      # Optional space-separated scopes (default: "openid email profile")
      WF_OIDC_SCOPES: "${WF_OIDC_SCOPES:-}"
      # Allowlist (comma-separated). With NEITHER set the server refuses to start
      # unless WF_OIDC_ALLOW_ANY=true is set — a missing allowlist must not silently
      # grant every IdP user access.
      WF_OIDC_ALLOWED_EMAILS: "${WF_OIDC_ALLOWED_EMAILS:-}"
      WF_OIDC_ALLOWED_SUBS: "${WF_OIDC_ALLOWED_SUBS:-}"
      # Set "true" to allow ANY IdP-authenticated user when no allowlist is set
      # (only safe on a dedicated single-user IdP).
      WF_OIDC_ALLOW_ANY: "${WF_OIDC_ALLOW_ANY:-}"
      # Logout ends the IdP session too when supported (RP-Initiated Logout). To return
      # to the app afterward, set this AND register it in the IdP; otherwise omit it.
      WF_OIDC_POST_LOGOUT_REDIRECT_URL: "${WF_OIDC_POST_LOGOUT_REDIRECT_URL:-}"
      # Set to "false" to force local-only logout even when the IdP supports RP-Initiated Logout.
      WF_OIDC_RP_LOGOUT: "${WF_OIDC_RP_LOGOUT:-}"

      # ── AI Agent Access / MCP (optional) ────────────────────────────────
      # Requires Wealthfolio authentication via password or OIDC.
      WF_MCP_ENABLED: "${WF_MCP_ENABLED:-false}"
      WF_MCP_AUDIT_ENABLED: "${WF_MCP_AUDIT_ENABLED:-true}"

      # Required when auth is enabled — set to your app's origin, e.g. https://wealthfolio.example.com
      WF_CORS_ALLOW_ORIGINS: "${WF_CORS_ALLOW_ORIGINS:-}"
      WF_REQUEST_TIMEOUT_MS: "${WF_REQUEST_TIMEOUT_MS:-30000}"
    healthcheck:
      test:
        ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://127.0.0.1:8088/api/v1/healthz"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 15s
    deploy:
      resources:
        limits:
          memory: 512M
        reservations:
          memory: 128M
    security_opt:
      - no-new-privileges:true
    read_only: true
    tmpfs:
      - /tmp:size=64M

volumes:
  wealthfolio-data:
    driver: local

From the app's own repository: github.com/wealthfolio/wealthfolio/blob/1e08bbc/compose.yml.

Compose file from the app repository.

Install

  1. Docker with the Compose plugin (github.com/wealthfolio/wealthfolio/blob/1e08bbc/compose.yml)

    A host with Docker and the Docker Compose plugin. This entry runs from a compose file.

  2. Save the compose file as compose.yml (github.com/wealthfolio/wealthfolio/blob/1e08bbc/compose.yml)

    Use the compose file shown above.

  3. Start it (github.com/wealthfolio/wealthfolio/blob/1e08bbc/compose.yml)
    docker compose up -d
  4. Open the app (github.com/wealthfolio/wealthfolio/blob/1e08bbc/compose.yml)

    Open http://localhost:8088. The compose file publishes host port 8088 for the wealthfolio service.

Compose file check: config_ok on 2026-10-22.

Gotchas and maintenance

Gotchas

Signals

  • Open issues and pull requests: 534
  • Last push: 2026-10-22 (0 days before this page was built)
  • Latest release: v3.10.0 on 2026-10-14 (7 days before this page was built)