Ghostfolio
Open Source Wealth Management Software
Ghostfol.io | Live Demo | Ghostfolio Premium | FAQ | Blog | LinkedIn | Slack | X
Ghostfolio is an open source wealth management software built with web technology. The application empowers busy people to keep track of stocks, ETFs or cryptocurrencies and make solid, data-driven investment decisions. The software is designed for personal use in continuous operation.
Ghostfolio Premium
Our official Ghostfolio Premium cloud offering is the easiest way to get started. Due to the time it saves, this will be the best option for most people. Revenue is used to cover operational costs for the hosting infrastructure and professional data providers, and to fund ongoing development.
If you prefer to run Ghostfolio on your own infrastructure, please find further instructions in the Self-hosting section.
Why Ghostfolio?
Ghostfolio is for you if you are...
- 💼 trading stocks, ETFs or cryptocurrencies on multiple platforms
- 🏦 pursuing a buy & hold strategy
- 🎯 interested in getting insights of your portfolio composition
- 👻 valuing privacy and data ownership
- 🧘 into minimalism
- 🧺 caring about diversifying your financial resources
- 🆓 interested in financial independence
- 🙅 saying no to spreadsheets
- 😎 still reading this list
Features
- ✅ Create, update and delete transactions
- ✅ Multi account management
- ✅ Portfolio performance: Return on Average Investment (ROAI) including dividends (total return) for
Today,WTD,MTD,YTD,1Y,5Y,Max - ✅ Various charts
- ✅ Static analysis to identify potential risks in your portfolio
- ✅ Import and export transactions
- ✅ Dark Mode
- ✅ Zen Mode
- ✅ Progressive Web App (PWA) with a mobile-first design
Technology Stack
Ghostfolio is a modern web application written in TypeScript and organized as an Nx workspace.
Backend
The backend is based on NestJS using PostgreSQL as a database together with Prisma and Redis for caching.
Frontend
The frontend is built with Angular and uses Angular Material with utility classes from Bootstrap.
Self-hosting
We provide official container images hosted on Docker Hub for linux/amd64, linux/arm/v7 and linux/arm64.
Find answers to commonly asked questions about self-hosting Ghostfolio in our Frequently Asked Questions (FAQ) section.
Supported Environment Variables
| Name | Type | Default Value | Description |
| --------------------------------- | --------------------- | --------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| ACCESS_TOKEN_SALT | string | | A random string used as salt for access tokens |
| API_KEY_COINGECKO_DEMO | string (optional) | | The _CoinGecko_ Demo API key |
| API_KEY_COINGECKO_PRO | string (optional) | | The _CoinGecko_ Pro API key |
| DATABASE_URL | string | | The database connection URL. If using a connection pooler, use the pooled connection URL here. e.g. postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@localhost:5432/${POSTGRES_DB} |
| DIRECT_URL | string (optional) | | The direct database connection URL used by the _Prisma CLI_ (e.g. for schema migrations) and seeding, bypassing any connection poolers (falls back to DATABASE_URL) |
| ENABLE_FEATURE_AUTH_TOKEN | boolean (optional) | true | Enables authentication via security token |
| ENABLE_FEATURE_MCP | boolean (optional) | false | Enables the server of the _Model Context Protocol_ (MCP) at /mcp (experimental) |
| ENABLE_FEATURE_SECURITY_HEADERS | boolean (optional) | false | Enables HTTP security headers, e.g. Content-Security-Policy and X-Frame-Options (experimental). Other origins cannot embed pages (e.g. via iframe) or resources of Ghostfolio. Strict-Transport-Security is not set, because it requires HTTPS: set it in the reverse proxy |
| HOST | string (optional) | 0.0.0.0 | The host where the Ghostfolio application will run on |
| JWT_SECRET_KEY | string | | A random string used for _JSON Web Tokens_ (JWT) |
| LOG_LEVELS | string[] (optional) | | The logging levels for the Ghostfolio application, e.g. ["debug","error","log","warn"] |
| PORT | number (optional) | 3333 | The port where the Ghostfolio application will run on |
| POSTGRES_DB | string | | The name of the _PostgreSQL_ database |
| POSTGRES_PASSWORD | string | | The password of the _PostgreSQL_ database |
| POSTGRES_USER | string | | The user of the _PostgreSQL_ database |
| REDIS_DB | number (optional) | 0 | The database index of _Redis_ |
| REDIS_HOST | string | | The host where _Redis_ is running |
| REDIS_PASSWORD | string | | The password of _Redis_ |
| REDIS_PORT | number | | The port where _Redis_ is running |
| REDIS_TLS | boolean (optional) | false | Enables TLS/SSL connection to _Redis_ |
| REQUEST_TIMEOUT | number (optional) | 3000 | The timeout of network requests to data providers in milliseconds |
| ROOT_URL | string (optional) | http://0.0.0.0:3333 | The root URL of the Ghostfolio application, used for generating callback URLs and external links. |
| TRUST_PROXY | string (optional) | | The trust proxy setting of _Express.js_ to determine the client IP address for rate limiting, e.g. 1 if the Ghostfolio application runs behind a single reverse proxy |
OpenID Connect OIDC (experimental)
| Name | Type | Default Value | Description |
| -------------------------- | --------------------- | ------------------------------------ | ---------------------------------------------------------------------------------------------------- |
| ENABLE_FEATURE_AUTH_OIDC | boolean (optional) | false | Enables authentication via _OpenID Connect_ |
| OIDC_AUTHORIZATION_URL | string (optional) | | Manual override for the OIDC authorization endpoint (falls back to the discovery from the issuer) |
| OIDC_CALLBACK_URL | string (optional) | ${ROOT_URL}/api/auth/oidc/callback | The OIDC callback URL |
| OIDC_CLIENT_ID | string | | The OIDC client ID |
| OIDC_CLIENT_SECRET | string | | The OIDC client secret |
| OIDC_ISSUER | string | | The OIDC issuer URL, used to discover the OIDC configuration via /.well-known/openid-configuration |
| OIDC_SCOPE | string[] (optional) | ["openid"] | The OIDC scope to request, e.g. ["email","openid","profile"] |
| OIDC_TOKEN_URL | string (optional) | | Manual override for the OIDC token endpoint (falls back to the discovery from the issuer) |
| OIDC_USER_INFO_URL | string (optional) | | Manual override for the OIDC user info endpoint (falls back to the discovery from the issuer) |
Run with Docker Compose
Prerequisites
- Basic knowledge of Docker
- Installation of Docker
- Create a local copy of this Git repository (clone)
- Copy the file
.env.exampleto.envand populate it with your data (cp .env.example .env)
a. Run environment
Run the following command to start the Docker images from Docker Hub:
docker compose -f docker/docker-compose.yml up -d
b. Build and run environment
Run the following commands to build and start the Docker images:
docker compose -f docker/docker-compose.build.yml build
docker compose -f docker/docker-compose.build.yml up -d
Setup
- Open http://localhost:3333 in your browser
- Create a new user via _Get Started_ (this first user will get the role
ADMIN)
Upgrade Version
- Update the _Ghostfolio_ Docker image
ghostfolio/ghostfolio Docker image in docker/docker-compose.yml
- Run the following command if ghostfolio:latest is set:
docker compose -f docker/docker-compose.yml pull
- Run the following command to start the new Docker image:
docker compose -f docker/docker-compose.yml up -d
The container will automatically apply any required database schema migrations during startup.
Home Server Systems (Community)
Ghostfolio is available for various home server systems, including CasaOS, Easypanel, Home Assistant, Runtipi, TrueCharts, Umbrel, and Unraid.
Development
For detailed information on the environment setup and development process, please refer to DEVELOPMENT.md.
Public API
Authorization: Bearer Token
Set the header for each request as follows:
"Authorization": "Bearer eyJh..."
You can get the _Bearer Token_ via POST http://localhost:3333/api/v1/auth/anonymous (Body: { "accessToken": ")
Health Check (experimental)
The endpoint checks the connection to the database and to _Redis_. It is suitable as the readiness probe of an orchestrator (e.g. readinessProbe in _Kubernetes_) and as the healthcheck in _Docker Compose_. The check of _Redis_ can take up to 5 seconds. Thus, set the timeout of the probe to at least 5 seconds (e.g. timeoutSeconds: 5 in _Kubernetes_).
Request
GET http://localhost:3333/api/v1/health
Info: No Bearer Token is required for health check
Response
##### Success
200 OK
{
"status": "OK"
}
Liveness Probe (experimental)
The endpoint answers without a check of the database or _Redis_. It is suitable as the liveness probe of an orchestrator (e.g. livenessProbe in _Kubernetes_), so that an outage of a dependency after the start does not restart the container. The database migrations run before the server starts. Thus, also use the endpoint as the startup probe (e.g. startupProbe in _Kubernetes_), so that a long migration does not restart the container.
Request
GET http://localhost:3333/api/v1/health/liveness
Info: No Bearer Token is required for liveness probe
Response
##### Success
200 OK
{
"status": "OK"
}
Import Portfolio Data
Prerequisites
Bearer Token for authorization
Request
POST http://localhost:3333/api/v1/import
Body
{
"activities": [
{
"currency": "USD",
"dataSource": "YAHOO",
"date": "2021-09-15T00:00:00.000Z",
"fee": 19,
"quantity": 5,
"symbol": "MSFT",
"type": "BUY",
"unitPrice": 298.58
}
]
}
| Field | Type | Description |
| ------------ | ------------------- | ------------------------------------------------------------------- |
| accountId | string (optional) | Id of the account |
| comment | string (optional) | Comment of the activity |
| currency | string | CHF \| EUR \| USD etc. |
| dataSource | string | COINGECKO \| GHOSTFOLIO [^1] \| MANUAL \| YAHOO |
| date | string | Date in the format ISO-8601 |
| fee | number | Fee of the activity |
| quantity | number | Quantity of the activity |
| symbol | string | Symbol of the activity (suitable for dataSource) |
| type | string | BUY \| DIVIDEND \| FEE \| INTEREST \| LIABILITY \| SELL |
| unitPrice | number | Price per unit of the activity |
Response
##### Success
201 Created
##### Error
400 Bad Request
{
"error": "Bad Request",
"message": [
"activities.1 is a duplicate activity"
]
}
Export Portfolio Data
Prerequisites
Bearer Token for authorization
Request
GET http://localhost:3333/api/v1/export
Response
##### Success
200 OK
Portfolio (experimental)
Prerequisites
Grant access of type _Public_ in the _Access_ tab of _My Ghostfolio_.
Request
GET http://localhost:3333/api/v1/public/
Info: No Bearer Token is required for authorization
Response
##### Success
{
"performance": {
"1d": {
"relativeChange": 0 // normalized from -1 to 1
};
"ytd": {
"relativeChange": 0 // normalized from -1 to 1
},
"max": {
"relativeChange": 0 // normalized from -1 to 1
}
}
}
Update Asset Profile Data (experimental)
Prerequisites
Bearer Token for authorization with admin role
Request
PATCH http://localhost:3333/api/v1/asset-profiles/
Body
{
"countries": [
{
"code": "US",
"weight": 1
}
],
"sectors": [
{
"name": "Technology",
"weight": 1
}
]
}
| Field | Type | Description |
| ----------- | ------------------ | ---------------------------------------------------------------------- |
| countries | array (optional) | Countries with code (ISO 3166-1 alpha-2) and weight (0 to 1) |
| holdings | array (optional) | Holdings with name and weight (0 to 1) |
| sectors | array (optional) | Sectors with name and weight (0 to 1) |
Response
##### Success
200 OK
##### Error
404 Not Found
{
"error": "Not Found",
"message": "Could not find the asset profile for MSFT (YAHOO)"
}
Model Context Protocol (experimental)
The _Model Context Protocol_ (MCP) server lets an AI client read your portfolio, import activities into it and update the cash balances of your accounts.
Prerequisites
- Set
ENABLE_FEATURE_MCPtotrue - Set
ROOT_URLto the public URL of your instance if a client calls the endpoint from a browser page. The host name ofROOT_URLis the only accepted origin. - Grant an access of the type _MCP_ in _My Ghostfolio_ under _Access_ and copy its token
Connect a client
Point the client to the endpoint below and set the MCP access token as the _Bearer Token_.
POST http://localhost:3333/mcp
"Authorization": "Bearer <INSERT_MCP_ACCESS_TOKEN>"
Community Projects
Discover a variety of community projects for Ghostfolio: https://github.com/topics/ghostfolio
Are you building your own project? Add the ghostfolio topic to your _GitHub_ repository to get listed as well. Learn more →
Contributing
Ghostfolio is 100% free and open source. We support an active and healthy community and welcome contributions from everyone, including you.
Not sure what to work on? We have some ideas, even for newcomers. Please join the Ghostfolio Slack channel or post to @ghostfolio\_ on _X_. We would love to hear from you.
Sponsors
If you like to support this project, get Ghostfolio Premium, become a Sponsor or Buy me a coffee.
License
© 2021 - 2026 Ghostfolio
Licensed under the AGPLv3 License.
[^1]: Available with Ghostfolio Premium.

