# 03-ghostfolio.md

kstack:
  book: Centerpoint Home Lab
  chapter: Finance
  page: Ghostfolio
  tags: [ghostfolio, investments, portfolio, finance, postgres, redis]
---

## Overview

Ghostfolio is an open-source wealth management and investment portfolio tracker.
It aggregates holdings across accounts, tracks performance, and visualises
asset allocation. Internal-only access via Step-CA TLS — no external route is
configured. Ghostfolio manages its own user authentication. The stack is three
containers: the application, a PostgreSQL 15 database, and Redis for caching.

## Access

| Type     | URL                               | Auth                               |
|----------|-----------------------------------|------------------------------------|
| Internal | `https://ghostfolio.home.local`   | Ghostfolio own auth (Step-CA TLS)  |

No external route — accessible only on the LAN.

## Containers

| Container           | Image                      | Role                  |
|---------------------|----------------------------|-----------------------|
| `ghostfolio`        | `ghostfolio/ghostfolio:latest` | Web application    |
| `ghostfolio-postgres` | `postgres:15-alpine`     | PostgreSQL 15 database|
| `ghostfolio-redis`  | `redis:alpine`             | Cache and session store|

### ghostfolio (application)

**Runtime:** Node.js 22

**Key environment variables:**

| Variable          | Value / Notes                      |
|-------------------|------------------------------------|
| `DATABASE_URL`    | **REDACTED** (PostgreSQL connection string with password) |
| `REDIS_HOST`      | `ghostfolio-redis`                 |
| `REDIS_PORT`      | `6379`                             |
| `ACCESS_TOKEN_SALT` | **REDACTED**                     |
| `JWT_SECRET_KEY`  | **REDACTED**                       |
| `NODE_ENV`        | `production`                       |
| `TZ`              | `America/Toronto`                  |

No bind mounts — application state is stored entirely in PostgreSQL.

### ghostfolio-postgres (PostgreSQL 15)

**Image:** `postgres:15-alpine`

| Variable         | Value           |
|------------------|-----------------|
| `POSTGRES_DB`    | `ghostfoliodb`  |
| `POSTGRES_USER`  | `ghostfoliouser`|
| `POSTGRES_PASSWORD` | **REDACTED** |
| `TZ`             | `America/Toronto` |

**Bind mounts:**

| Host Path                                      | Container Path             |
|------------------------------------------------|----------------------------|
| `/home/jeeves/docker/ghostfolio/postgres_data` | `/var/lib/postgresql/data` |

### ghostfolio-redis

**Image:** `redis:alpine`

No authentication configured — network-isolated to the Ghostfolio internal
stack network.

**Bind mounts:**

| Host Path                                   | Container Path |
|---------------------------------------------|----------------|
| `/home/jeeves/docker/ghostfolio/redis_data` | `/data`        |

## Traefik Labels

```yaml
traefik.http.routers.ghostfolio.rule: Host(`ghostfolio.home.local`)
traefik.http.routers.ghostfolio.entrypoints: websecure
traefik.http.routers.ghostfolio.tls.certresolver: step-ca
traefik.http.services.ghostfolio.loadbalancer.server.port: 3333
```

## Notes / Gotchas

- `ACCESS_TOKEN_SALT` and `JWT_SECRET_KEY` are critical secrets. If lost, all
  existing sessions and API tokens will be invalidated and cannot be recovered
  without reconfiguring Ghostfolio.
- Ghostfolio fetches market data from various external providers (Yahoo Finance,
  Coingecko, etc.). Market data API rate limits may apply depending on configured
  data sources.
- Portfolio data import supports CSV and JSON formats compatible with common
  brokerages. Check the Ghostfolio docs for the required format.
- Redis stores only ephemeral cache — data is not critical and does not need to
  be backed up. The `postgres_data` bind mount is the primary backup target.
- Port 3333 is the default Ghostfolio application port.

---
*Last Updated: 2026-06-17*