diff --git a/README.md b/README.md index 4ee04117d..8acc93646 100644 --- a/README.md +++ b/README.md @@ -327,6 +327,130 @@ The final image includes: - `wealthfolio-server` binary at `/usr/local/bin/wealthfolio-server` - Alpine Linux base (small footprint) +### Using Docker Compose + +The easiest way to run Wealthfolio locally is using Docker Compose. A `docker-compose.yml` file is provided in the repository root. + +#### Quick Start + +**Option 1: Use pre-built image** (faster, recommended): + +1. **Set the secret key** (required): + +```bash +export WF_SECRET_KEY=$(openssl rand -base64 32) +``` + +2. **Start the service**: + +```bash +docker compose up -d +``` + +**Option 2: Build from source** (for development or custom builds): + +1. **Set the secret key**: + +```bash +export WF_SECRET_KEY=$(openssl rand -base64 32) +``` + +2. **Build and start**: + +```bash +docker compose build +docker compose up -d +``` + +Or in a single command: + +```bash +WF_SECRET_KEY=$(openssl rand -base64 32) docker compose up -d --build +``` + +3. **Access the application**: + +Open your browser at `http://localhost:8088` + +#### Development Mode + +For development with CORS enabled for local Vite dev server: + +**Using pre-built image:** + +```bash +# Generate secret key and start dev service +export WF_SECRET_KEY=$(openssl rand -base64 32) && docker compose --profile dev up -d wealthfolio-dev +``` + +**Building from source:** + +```bash +# Build and start dev service +export WF_SECRET_KEY=$(openssl rand -base64 32) && docker compose --profile dev build && docker compose --profile dev up -d wealthfolio-dev +``` + +Or as a single command: + +```bash +WF_SECRET_KEY=$(openssl rand -base64 32) docker compose --profile dev up -d --build wealthfolio-dev +``` + +**Note:** The development profile requires `WF_SECRET_KEY` to be set. The service will not start without a valid base64-encoded 32-byte secret key. + +#### Useful Commands + +```bash +# View logs +docker compose logs -f + +# Stop the service +docker compose down + +# Stop and remove volumes (WARNING: deletes all data!) +docker compose down -v + +# Restart the service +docker compose restart + +# Check service status +docker compose ps + +# Rebuild the image (if building from source) +docker compose build + +# Rebuild and restart +docker compose up -d --build +``` + +#### Configuration + +You can configure the service using environment variables. Create a `.env` file in the project root: + +```bash +WF_PORT=8088 +WF_SECRET_KEY=your-secret-key-here +WF_CORS_ALLOW_ORIGINS=* +``` + +Or set them inline: + +```bash +WF_SECRET_KEY=$(openssl rand -base64 32) docker compose up -d +``` + +#### Volumes + +Data is persisted in the `wealthfolio-data` Docker volume: +- Database: `/data/wealthfolio.db` (inside container) +- Secrets: `/data/secrets.json` (encrypted with `WF_SECRET_KEY`) + +To find the volume location on your host: + +```bash +docker volume inspect wealthfolio_wealthfolio-data +``` + ### Configuration You can configure the container using either: diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 000000000..189a8091a --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,78 @@ +services: + wealthfolio: + # Builds from source if image doesn't exist, or use --build flag to force rebuild + # To use pre-built image: docker compose up -d + # To build from source: docker compose up -d --build + image: ${DOCKER_IMAGE:-afadil/wealthfolio:latest} + build: + context: . + dockerfile: Dockerfile + container_name: wealthfolio + restart: unless-stopped + ports: + - "${WF_PORT:-8088}:8080" + volumes: + - wealthfolio-data:/data + environment: + # Server Configuration + - WF_LISTEN_ADDR=0.0.0.0:8080 + - WF_DB_PATH=/data/wealthfolio.db + - WF_STATIC_DIR=dist + - WF_CORS_ALLOW_ORIGINS=${WF_CORS_ALLOW_ORIGINS:-*} + - WF_REQUEST_TIMEOUT_MS=${WF_REQUEST_TIMEOUT_MS:-30000} + + # Security (required for production) + - WF_SECRET_KEY=${WF_SECRET_KEY:-} + + # Authentication (optional) + - WF_AUTH_PASSWORD_HASH=${WF_AUTH_PASSWORD_HASH:-} + - WF_AUTH_TOKEN_TTL_MINUTES=${WF_AUTH_TOKEN_TTL_MINUTES:-60} + + # Optional + - WF_SECRET_FILE=${WF_SECRET_FILE:-/data/secrets.json} + - WF_ADDONS_DIR=${WF_ADDONS_DIR:-} + healthcheck: + test: + [ + "CMD", + "wget", + "--quiet", + "--tries=1", + "--spider", + "http://localhost:8080/api/v1/healthz", + ] + interval: 30s + timeout: 10s + retries: 3 + start_period: 10s + + # Development profile with CORS enabled for local Vite dev server + # Note: WF_SECRET_KEY must be provided via environment variable + # Use: export WF_SECRET_KEY=$(openssl rand -base64 32) && docker compose --profile dev up -d wealthfolio-dev + wealthfolio-dev: + # Builds from source if image doesn't exist, or use --build flag to force rebuild + # To use pre-built image: docker compose --profile dev up -d wealthfolio-dev + # To build from source: docker compose --profile dev up -d --build wealthfolio-dev + image: ${DOCKER_IMAGE:-afadil/wealthfolio:latest} + build: + context: . + dockerfile: Dockerfile + container_name: wealthfolio-dev + restart: unless-stopped + ports: + - "${WF_PORT:-8088}:8080" + volumes: + - wealthfolio-data:/data + environment: + - WF_LISTEN_ADDR=0.0.0.0:8080 + - WF_DB_PATH=/data/wealthfolio.db + - WF_STATIC_DIR=dist + - WF_CORS_ALLOW_ORIGINS=http://localhost:1420,http://localhost:3000 + - WF_REQUEST_TIMEOUT_MS=30000 + - WF_SECRET_KEY=${WF_SECRET_KEY} + profiles: + - dev + +volumes: + wealthfolio-data: + driver: local