JOIDY
DOCUMENTATION MENU

Configuration

Complete configuration reference for Joidy via environment variables.

Configuration

All configuration is done via environment variables in .env. After a git clone, copy .env.example to .env; system installs (curl script, Homebrew, AUR) keep it at ~/.config/joidy/.env.

Required

| Variable | Description | |----------|-------------| | GEMINI_API_KEY | Google Gemini API key — AI Studio. AI features are disabled without a provider key, but the app still works | | OBSIDIAN_VAULT_PATH | Absolute host path to your Obsidian vault (~ is expanded). Mounted read-write at /vault in the worker | | SECRET_KEY | Session/JWT signing key — generate with openssl rand -hex 32 |

AI Providers

Joidy supports 6 providers through a factory in ai-service. Set the API key for the providers you want, then pick the active one with LLM_MODEL.

| Variable | Default | Description | |----------|---------|-------------| | GEMINI_API_KEY | — | Google Gemini | | OPENAI_API_KEY | — | OpenAI | | ANTHROPIC_API_KEY | — | Anthropic | | COHERE_API_KEY | — | Cohere | | OPENROUTER_API_KEY | — | OpenRouter | | OLLAMA_BASE_URL | http://host.docker.internal:11434 | Local Ollama endpoint — no key needed | | LLM_MODEL | gemini:gemini-2.0-flash | Active chat/classification model, provider:model format | | EMBEDDING_MODEL | gemini:models/text-embedding-004 | Embedding model, provider:model format | | AI_SERVICE_ENABLED | true | Set false to disable AI calls entirely |

Obsidian

| Variable | Description | |----------|-------------| | OBSIDIAN_VAULT_PATH | Host path to vault; also used by the API for vault file ops | | OBSIDIAN_WEBHOOK_SECRET | Shared secret for POST /webhook/obsidian — enables instant push sync (see API Reference) |

Database

| Variable | Description | |----------|-------------| | POSTGRES_USER | joidy by default | | POSTGRES_PASSWORD | Password for the postgres container. Only applies at initdb — changing it on an existing volume breaks auth unless you update the role in Postgres | | POSTGRES_DB | joidy by default |

DATABASE_URL is composed automatically inside compose (postgresql://joidy:<password>@postgres:5432/joidy).

Integrations (optional)

| Variable | Description | |----------|-------------| | GITHUB_CLIENT_ID / GITHUB_CLIENT_SECRET | GitHub OAuth app | | GITHUB_TOKEN / GITHUB_USERNAME | Classic token sync alternative | | GITHUB_OAUTH_WEB_URL / GITHUB_WEBHOOK_URL | OAuth callback base / webhook endpoint | | GOOGLE_CLIENT_ID / GOOGLE_CLIENT_SECRET / GOOGLE_REDIRECT_URI | Google Calendar & Tasks OAuth (default redirect http://localhost:8000/integrations/google/callback) | | STRAVA_CLIENT_ID / STRAVA_CLIENT_SECRET / STRAVA_REDIRECT_URI | Strava integration | | SPOTIFY_CLIENT_ID / SPOTIFY_CLIENT_SECRET / SPOTIFY_REDIRECT_URI | Spotify integration | | TELEGRAM_BOT_TOKEN / TELEGRAM_ALLOWED_USER_ID | Telegram notifications |

Push Notifications

| Variable | Description | |----------|-------------| | VAPID_PUBLIC_KEY / VAPID_PRIVATE_KEY | Web Push VAPID keypair — without it, push is disabled gracefully | | VAPID_CLAIM_EMAIL | mailto: contact for the VAPID claim |

Server

| Variable | Default | Description | |----------|---------|-------------| | SECRET_KEY | — | JWT signing key (required) | | APP_ENV | development | development or production | | CORS_ALLOWED_ORIGINS | localhost dev fallback | Comma-separated allowed origins | | AUTH_PASSWORD | — | Single-user password for POST /auth/login. Required when APP_ENV=production — the API refuses to start without it | | FRONTEND_PORT / API_PORT / AI_SERVICE_PORT / WORKER_PORT | 3000 / 8000 / 8002 / 8001 | Host port overrides | | GRAFANA_ADMIN_PASSWORD | — | Required only when using docker-compose.monitoring.yml |

Example .env

SECRET_KEY=change_this_to_a_random_secret_key
GEMINI_API_KEY=your-key
OBSIDIAN_VAULT_PATH=~/Documents/obsidian/my-vault
POSTGRES_PASSWORD=a-strong-password

# Optional
LLM_MODEL=gemini:gemini-2.0-flash
TELEGRAM_BOT_TOKEN=
CORS_ALLOWED_ORIGINS=http://localhost:3000

Generating SECRET_KEY

openssl rand -hex 32
# or
python -c "import secrets; print(secrets.token_hex(32))"