How to Self-Host Ghostfolio with Docker Compose

What Is Ghostfolio?

Ghostfolio is an open-source wealth management dashboard that tracks stocks, ETFs, cryptocurrencies, and other assets in one place. It replaces paid portfolio trackers like Mint, Personal Capital (Empower), or Yahoo Finance Premium. Self-hosting keeps your financial data private — no third party sees your holdings, net worth, or transaction history.

Prerequisites

  • A Linux server (Ubuntu 22.04+ recommended)
  • Docker and Docker Compose installed (guide)
  • 1 GB of free disk space
  • 512 MB of RAM (minimum), 1 GB recommended
  • A domain name (optional, for remote access)

Docker Compose Configuration

Create a project directory and a docker-compose.yml file:

mkdir -p ~/ghostfolio && cd ~/ghostfolio
services:
  ghostfolio:
    image: ghostfolio/ghostfolio:2.249.0
    container_name: ghostfolio
    restart: unless-stopped
    ports:
      - "3333:3333"
    environment:
      DATABASE_URL: "postgresql://ghostfolio:${POSTGRES_PASSWORD}@postgres:5432/ghostfolio-db?connect_timeout=300&sslmode=prefer"
      REDIS_HOST: redis
      REDIS_PORT: 6379
      REDIS_PASSWORD: "${REDIS_PASSWORD}"
      ACCESS_TOKEN_SALT: "${ACCESS_TOKEN_SALT}"
      JWT_SECRET_KEY: "${JWT_SECRET_KEY}"
    depends_on:
      postgres:
        condition: service_healthy
      redis:
        condition: service_healthy
    security_opt:
      - no-new-privileges:true
    healthcheck:
      test: ["CMD-SHELL", "curl -f http://localhost:3333/api/v1/health || exit 1"]
      interval: 10s
      timeout: 5s
      retries: 5

  postgres:
    image: postgres:15-alpine
    container_name: ghostfolio-db
    restart: unless-stopped
    environment:
      POSTGRES_USER: ghostfolio
      POSTGRES_PASSWORD: "${POSTGRES_PASSWORD}"
      POSTGRES_DB: ghostfolio-db
    volumes:
      - postgres-data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U ghostfolio -d ghostfolio-db"]
      interval: 10s
      timeout: 5s
      retries: 5

  redis:
    image: redis:7-alpine
    container_name: ghostfolio-redis
    restart: unless-stopped
    command: ["redis-server", "--requirepass", "${REDIS_PASSWORD}"]
    user: "999:1000"
    healthcheck:
      test: ["CMD", "redis-cli", "-a", "${REDIS_PASSWORD}", "ping"]
      interval: 10s
      timeout: 5s
      retries: 5

volumes:
  postgres-data:

Create a .env file alongside docker-compose.yml:

# Database password — change this to a strong password
POSTGRES_PASSWORD=change-me-to-a-secure-password

# Redis password — change this to a strong password
REDIS_PASSWORD=change-me-to-another-secure-password

# Token salt for access tokens — generate with: openssl rand -hex 32
ACCESS_TOKEN_SALT=generate-a-random-string-here

# JWT secret key — generate with: openssl rand -hex 32
JWT_SECRET_KEY=generate-another-random-string-here

Generate secure random values for the secrets:

sed -i "s/change-me-to-a-secure-password/$(openssl rand -hex 16)/" .env
sed -i "s/change-me-to-another-secure-password/$(openssl rand -hex 16)/" .env
sed -i "s/generate-a-random-string-here/$(openssl rand -hex 32)/" .env
sed -i "s/generate-another-random-string-here/$(openssl rand -hex 32)/" .env

Start the stack:

docker compose up -d

Initial Setup

  1. Open http://your-server-ip:3333 in your browser
  2. Click Get Started to create your first account
  3. The first user created automatically gets the ADMIN role
  4. Add your first portfolio and start importing transactions

There are no default credentials — the first registered user becomes the administrator.

Configuration

SettingDescription
ACCESS_TOKEN_SALTRandom string used to generate access tokens. Once set, do not change — existing tokens will break.
JWT_SECRET_KEYSecret for JWT signing. Changing this invalidates all active sessions.
DATABASE_URLFull PostgreSQL connection string. Modify if using an external database.
REDIS_PASSWORDPassword for Redis authentication. Must match between the Ghostfolio and Redis containers.

Ghostfolio supports importing transactions via CSV or its API (POST /api/v1/import). Supported transaction types include BUY, SELL, DIVIDEND, FEE, INTEREST, and LIABILITY.

Advanced Configuration (Optional)

Data Provider Integration

Ghostfolio fetches market data from various providers. By default it uses Yahoo Finance (no API key needed). For more reliable data, you can configure:

# Add to ghostfolio environment in docker-compose.yml
environment:
  # ... existing vars ...
  DATA_SOURCE_PRIMARY: YAHOO  # Default — free, no key needed

Disabling Public Registration

After creating your account, you can disable public registration through the admin panel at Admin → Settings.

Reverse Proxy

Ghostfolio runs on port 3333 by default. Put it behind a reverse proxy for SSL and domain access.

Example Nginx Proxy Manager configuration:

  • Scheme: http
  • Forward Hostname: ghostfolio (or your container IP)
  • Forward Port: 3333

For detailed setup: Reverse Proxy Setup

Backup

Back up the PostgreSQL database volume:

docker exec ghostfolio-db pg_dump -U ghostfolio ghostfolio-db > ghostfolio-backup-$(date +%Y%m%d).sql

Restore from backup:

cat ghostfolio-backup-20260224.sql | docker exec -i ghostfolio-db psql -U ghostfolio ghostfolio-db

The postgres-data volume contains all your financial data. Include it in your backup rotation. See Backup Strategy for a comprehensive approach.

Troubleshooting

Ghostfolio won’t start — database connection errors

Symptom: Container exits with ECONNREFUSED or Connection refused errors. Fix: Ensure PostgreSQL is healthy before Ghostfolio starts. The depends_on with condition: service_healthy handles this. If PostgreSQL fails health checks, inspect its logs: docker logs ghostfolio-db.

Market data not loading

Symptom: Portfolio shows $0 or no price data for holdings. Fix: Yahoo Finance is the default data provider. Ensure your server has outbound internet access. Check the Ghostfolio logs: docker logs ghostfolio. If Yahoo Finance is unreliable in your region, consider configuring an alternative data provider.

Redis authentication errors

Symptom: NOAUTH Authentication required in Ghostfolio logs. Fix: Verify REDIS_PASSWORD matches between the Ghostfolio container’s environment and the Redis --requirepass flag. Check your .env file.

Database already initialized with different credentials

Symptom: PostgreSQL rejects connections after changing passwords. Fix: PostgreSQL initializes credentials on first run. If you change passwords after initialization, remove the volume and reinitialize:

docker compose down
docker volume rm ghostfolio_postgres-data
docker compose up -d

Warning: This deletes all data. Export your portfolio first.

Resource Requirements

ResourceRequirement
RAM~300 MB idle, ~500 MB under load (across all 3 containers)
CPULow — minimal background processing
Disk~500 MB for application, plus database growth based on transaction count

Verdict

Ghostfolio is the best self-hosted portfolio tracker for most people. It covers stocks, ETFs, crypto, and other assets with a clean dashboard that shows allocation, performance, and dividends at a glance. The setup is straightforward — three containers, no complex configuration.

If you only track a simple budget (income vs expenses), Actual Budget or Firefly III are better fits. Ghostfolio is specifically for investment portfolio tracking — it pulls live market data, calculates returns, and shows your net worth over time.

Comments