Environment
Every .env key explained — variants, 8 LLM providers, messaging channels, auth, rate limiting, and live data services.
Create your local environment file from one of the variant templates, then edit as needed. The file is gitignored — never commit it.
# Personal variant
cp .env.personal.example .env
# Business variant
cp .env.business.example .env.env may contain API keys, your name, and local paths. It is gitignored by default.
Variant
luna_variant=personal # personal | business| Value | Behaviour |
|---|---|
personal | Casual companion. Voice, vision, Spotify, desktop automation. Single user. No auth required by default. |
business | Professional team assistant. Multi-user JWT. Rate limiting. No personal features. Channels emphasised. |
Business-specific identity keys:
business_name=Acme Corp
business_description=a SaaS company building developer tools
# professional | friendly | technical | concise
business_tone=professionalLLM providers
Set llm_provider to one of the eight supported values, then fill in the matching key block. All providers stream tokens via the same interface — no other code changes needed.
Ollama (local, default)
llm_provider=ollama
ollama_base_url=http://localhost:11434
ollama_model=qwen2.5:7bAny model in ollama list can be used. Tested with qwen2.5:7b,qwen2.5:14b, and llama3.2:3b on low-end hardware.
OpenAI / OpenAI-compatible
llm_provider=openai-compatible
openai_base_url=https://api.openai.com/v1
openai_api_key=sk-...
openai_model=gpt-4o-miniWorks with any OpenAI-compatible endpoint: LM Studio, Jan.ai, llama.cpp server, vLLM, Together AI, and OpenRouter (which gives you access to every major model through one key).
NVIDIA NIM
llm_provider=nvidia-nim
nvidia_nim_base_url=https://integrate.api.nvidia.com/v1
nvidia_nim_api_key=nvapi-...
nvidia_nim_model=meta/llama-3.1-8b-instructUses NVIDIA NIM's OpenAI-compatible chat completions endpoint. Point the base URL at NVIDIA API Catalog or a self-hosted NIM.
Anthropic Claude (native)
llm_provider=anthropic
anthropic_api_key=sk-ant-...
anthropic_model=claude-sonnet-4-5Uses the Anthropic Messages API directly — no proxy needed. Recommended for the business variant.
Google Gemini (native)
llm_provider=google
google_api_key=AIza...
google_model=gemini-2.0-flashUses the Gemini REST API. Flash is fast and cheap; Pro gives longer context and stronger reasoning.
Groq (native — fastest cloud)
llm_provider=groq
groq_api_key=gsk_...
groq_model=llama-3.3-70b-versatileGroq runs inference on custom LPU chips at ~300 tokens/second. Free tier available. Best speed/quality ratio for cloud inference.
Cohere Command R (native)
llm_provider=cohere
cohere_api_key=...
cohere_model=command-r-plusMistral AI (native)
llm_provider=mistral
mistral_api_key=...
mistral_model=mistral-large-latestEuropean-hosted. GDPR-compliant. Strong coding and reasoning performance.
Use openai-compatible with OpenRouter to access Claude, Gemini, GPT-4o, Mistral, Llama, and more through a single key and pay-per-token billing:
llm_provider=openai-compatible
openai_base_url=https://openrouter.ai/api/v1
openai_api_key=sk-or-...
openai_model=anthropic/claude-opus-4Embeddings
Embeddings power memory search — finding semantically similar facts when building context.
# Ollama (default — pull nomic-embed-text once)
embedding_provider=ollama
ollama_embed_model=nomic-embed-text
# OpenAI-compatible (uses same base_url and api_key as LLM)
embedding_provider=openai-compatible
openai_embed_model=text-embedding-3-smallAuth & rate limiting
JWT (business / multi-user)
Set jwt_secret to enable per-user JWT tokens via the admin API. Admin requests must include Authorization: Bearer <jwt_secret>.
# Generate: openssl rand -hex 32
jwt_secret=your-64-char-hex-string
jwt_expiry_hours=720# Create a user and get a JWT
curl -X POST http://localhost:8899/api/admin/users \
-H "Authorization: Bearer YOUR_JWT_SECRET" \
-H "Content-Type: application/json" \
-d '{"username": "alice", "role": "user"}'
# → { "user_id": "...", "token": "eyJ..." }Rate limiting
rate_limit_enabled=true
rate_limit_per_minute=60 # requests per user per window
rate_limit_burst=20 # extra burst allowanceThe sliding-window rate limiter runs in-memory (no Redis required). The business Docker compose file enables rate limiting automatically.
GET /api/admin/info System info + provider status
GET /api/admin/users List users
POST /api/admin/users Create user (returns JWT)
DELETE /api/admin/users/{id} Revoke user
POST /api/admin/users/{id}/rotate-token Rotate JWT
GET /api/admin/llm/providers All configured providersMessaging channels
Luna can receive messages via Telegram, Discord, Slack, and a generic HTTP webhook. GitHub event notifications are covered in the GitHub section below. Each channel maintains isolated per-user conversation history. Desktop features (voice, Spotify, maps) are automatically stripped from channel replies.
Telegram
telegram_bot_token=123456:ABC-...Register the webhook after Luna is running at a public URL:
curl "https://api.telegram.org/bot<TOKEN>/setWebhook?url=https://YOUR_HOST/api/channels/telegram"Discord
discord_bot_token=MTI...
discord_public_key=abc123... # from Discord Developer PortalIn the Discord Developer Portal, set the Interactions Endpoint URL tohttps://YOUR_HOST/api/channels/discord. Luna handles the Ed25519 ping verification automatically.
Slack
slack_bot_token=xoxb-...
slack_signing_secret=abc...In your Slack App config, set the Events API Request URL tohttps://YOUR_HOST/api/channels/slack and subscribe tomessage.channels and app_mention.
Generic webhook
Any system can post to Luna over HTTP:
curl -X POST http://localhost:8899/api/channels/webhook \
-H "Content-Type: application/json" \
-d '{"user_id": "u1", "user_name": "Bob", "text": "summarise this week"}'
# → { "reply": "Here is this week's summary..." }# GET /api/channels/status returns which channels are configured
# { "telegram": true, "discord": false, "slack": true, "webhook": true }GitHub
Set github_token to enable GitHub tools in chat (list issues, create issues, comment on PRs). Set github_webhook_secret to receive push, PR, and issue events via the /api/channels/github endpoint.
# Personal Access Token — needs repo, issues, pull_requests read/write
github_token=ghp_...
# Webhook — must match the secret set in GitHub repo/org settings
github_webhook_secret=strong-random-secret
# Default repo for tool calls (owner/repo format)
github_default_repo=myorg/myrepo
# Forward GitHub event summaries to a notification channel (optional)
github_notify_slack_channel=C0123ABCDEF # Slack channel ID
github_notify_telegram_chat_id=123456789 # Telegram chat IDRegister the webhook in GitHub under Settings → Webhooks → Add webhook:
Payload URL: https://YOUR_HOST/api/channels/github
Content type: application/json
Secret: <same as github_webhook_secret>
Events: push, pull_request, issues, issue_comment, releaseA fine-grained PAT with Contents (read), Issues (read/write), and Pull requests (read) is sufficient. Classic tokens need the repo scope.
LAN / network mode
host=0.0.0.0Open http://YOUR_LAN_IP:8899 on any device on your network. For the business variant, set jwt_secret to protect the admin API.
Spotify (personal variant only)
Create a Spotify Developer app at developer.spotify.com and add http://localhost:8899/api/spotify/callback as a redirect URI.
spotify_client_id=your_client_id
spotify_client_secret=your_client_secretData services
| Key | Service | Notes |
|---|---|---|
the_news_api | TheNewsAPI | Live news headlines. Dashboard widget. Free tier available. |
alpha_vantage | Alpha Vantage | Extended market data. Falls back to Yahoo Finance without this. |
weather_lat/lon | Open-Meteo | Free, no key. Set your coordinates for accurate weather. |
weather_city | — | Display name for the weather widget. |
weather_timezone | — | IANA timezone string, e.g. America/New_York. |
Full reference
| Key | Default | Description |
|---|---|---|
luna_variant | personal | personal or business. |
business_name | — | Company name injected into business system prompt. |
business_description | — | One-line description of the organisation. |
business_tone | professional | professional | friendly | technical | concise. |
llm_provider | ollama | ollama | openai-compatible | nvidia-nim | anthropic | google | groq | cohere | mistral. |
ollama_base_url | http://localhost:11434 | Ollama server URL. |
ollama_model | qwen2.5:7b | Ollama chat model. |
ollama_embed_model | nomic-embed-text | Ollama embedding model. |
openai_base_url | https://api.openai.com/v1 | OpenAI-compatible base URL. |
openai_api_key | — | API key for OpenAI-compatible provider. |
openai_model | gpt-4o-mini | Model name. |
nvidia_nim_base_url | https://integrate.api.nvidia.com/v1 | NVIDIA NIM OpenAI-compatible base URL. |
nvidia_nim_api_key | — | NVIDIA API key. |
nvidia_nim_model | meta/llama-3.1-8b-instruct | NVIDIA NIM model ID. |
anthropic_api_key | — | Anthropic API key. |
anthropic_model | claude-sonnet-4-5 | Anthropic model ID. |
google_api_key | — | Google AI Studio API key. |
google_model | gemini-2.0-flash | Gemini model ID. |
groq_api_key | — | Groq API key. |
groq_model | llama-3.3-70b-versatile | Groq model ID. |
cohere_api_key | — | Cohere API key. |
cohere_model | command-r-plus | Cohere model ID. |
mistral_api_key | — | Mistral AI API key. |
mistral_model | mistral-large-latest | Mistral model ID. |
embedding_provider | ollama | ollama or openai-compatible. |
jwt_secret | — | Signs per-user JWT tokens. Admin API uses Authorization: Bearer <jwt_secret>. |
jwt_expiry_hours | 720 | JWT lifetime in hours (30 days default). |
rate_limit_enabled | false | Enable sliding-window rate limiting. |
rate_limit_per_minute | 60 | Max requests per user per 60-second window. |
rate_limit_burst | 20 | Extra burst allowance on top of the per-minute limit. |
telegram_bot_token | — | Telegram Bot API token from @BotFather. |
discord_bot_token | — | Discord bot token. |
discord_public_key | — | Discord app public key for interaction signature verification. |
slack_bot_token | — | Slack bot OAuth token (xoxb-...). |
slack_signing_secret | — | Slack app signing secret for request verification. |
github_token | — | GitHub Personal Access Token for API tools (list/create issues, PRs). |
github_webhook_secret | — | HMAC secret for verifying GitHub webhook payloads. |
github_default_repo | — | Default owner/repo for tool calls when no repo is specified. |
github_notify_slack_channel | — | Slack channel ID to forward GitHub event summaries to. |
github_notify_telegram_chat_id | — | Telegram chat ID to forward GitHub event summaries to. |
host | 127.0.0.1 | Backend bind address. 0.0.0.0 for LAN/Docker. |
port | 8899 | Backend HTTP port. |
user_name | friend | Your name — used in the personal variant system prompt. |
luna_name | L.U.N.A. | Assistant display name. |
spotify_client_id | — | Spotify Developer app client ID. |
spotify_client_secret | — | Spotify Developer app client secret. |
the_news_api | — | TheNewsAPI key for live news widget. |
alpha_vantage | — | Alpha Vantage key for extended market data. |
weather_lat | 40.7128 | Latitude for Open-Meteo weather. |
weather_lon | -74.0060 | Longitude for Open-Meteo weather. |
weather_city | New York | Display name for the weather widget. |
weather_timezone | America/New_York | IANA timezone string. |