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.

terminal
# Personal variant
cp .env.personal.example .env

# Business variant
cp .env.business.example .env
⚠️
Never commit .env

.env may contain API keys, your name, and local paths. It is gitignored by default.

Variant

.env
luna_variant=personal   # personal | business
ValueBehaviour
personalCasual companion. Voice, vision, Spotify, desktop automation. Single user. No auth required by default.
businessProfessional team assistant. Multi-user JWT. Rate limiting. No personal features. Channels emphasised.

Business-specific identity keys:

.env
business_name=Acme Corp
business_description=a SaaS company building developer tools
# professional | friendly | technical | concise
business_tone=professional

LLM 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)

.env
llm_provider=ollama
ollama_base_url=http://localhost:11434
ollama_model=qwen2.5:7b

Any 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

.env
llm_provider=openai-compatible
openai_base_url=https://api.openai.com/v1
openai_api_key=sk-...
openai_model=gpt-4o-mini

Works 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

.env
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-instruct

Uses NVIDIA NIM's OpenAI-compatible chat completions endpoint. Point the base URL at NVIDIA API Catalog or a self-hosted NIM.

Anthropic Claude (native)

.env
llm_provider=anthropic
anthropic_api_key=sk-ant-...
anthropic_model=claude-sonnet-4-5

Uses the Anthropic Messages API directly — no proxy needed. Recommended for the business variant.

Google Gemini (native)

.env
llm_provider=google
google_api_key=AIza...
google_model=gemini-2.0-flash

Uses the Gemini REST API. Flash is fast and cheap; Pro gives longer context and stronger reasoning.

Groq (native — fastest cloud)

.env
llm_provider=groq
groq_api_key=gsk_...
groq_model=llama-3.3-70b-versatile

Groq runs inference on custom LPU chips at ~300 tokens/second. Free tier available. Best speed/quality ratio for cloud inference.

Cohere Command R (native)

.env
llm_provider=cohere
cohere_api_key=...
cohere_model=command-r-plus

Mistral AI (native)

.env
llm_provider=mistral
mistral_api_key=...
mistral_model=mistral-large-latest

European-hosted. GDPR-compliant. Strong coding and reasoning performance.

ℹ️
OpenRouter — one key, every model

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-4

Embeddings

Embeddings power memory search — finding semantically similar facts when building context.

.env
# 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-small

Auth & 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>.

.env
# Generate: openssl rand -hex 32
jwt_secret=your-64-char-hex-string
jwt_expiry_hours=720
terminal
# 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

.env
rate_limit_enabled=true
rate_limit_per_minute=60   # requests per user per window
rate_limit_burst=20        # extra burst allowance

The sliding-window rate limiter runs in-memory (no Redis required). The business Docker compose file enables rate limiting automatically.

ℹ️
Admin API endpoints
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 providers

Messaging 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

.env
telegram_bot_token=123456:ABC-...

Register the webhook after Luna is running at a public URL:

terminal
curl "https://api.telegram.org/bot<TOKEN>/setWebhook?url=https://YOUR_HOST/api/channels/telegram"

Discord

.env
discord_bot_token=MTI...
discord_public_key=abc123...  # from Discord Developer Portal

In the Discord Developer Portal, set the Interactions Endpoint URL tohttps://YOUR_HOST/api/channels/discord. Luna handles the Ed25519 ping verification automatically.

Slack

.env
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:

terminal
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..." }
.env (status check)
# 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.

.env
# 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 ID

Register the webhook in GitHub under Settings → Webhooks → Add webhook:

GitHub webhook settings
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, release
💡
Token scopes

A fine-grained PAT with Contents (read), Issues (read/write), and Pull requests (read) is sufficient. Classic tokens need the repo scope.

LAN / network mode

.env
host=0.0.0.0

Open 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.

.env
spotify_client_id=your_client_id
spotify_client_secret=your_client_secret

Data services

KeyServiceNotes
the_news_apiTheNewsAPILive news headlines. Dashboard widget. Free tier available.
alpha_vantageAlpha VantageExtended market data. Falls back to Yahoo Finance without this.
weather_lat/lonOpen-MeteoFree, no key. Set your coordinates for accurate weather.
weather_cityDisplay name for the weather widget.
weather_timezoneIANA timezone string, e.g. America/New_York.

Full reference

KeyDefaultDescription
luna_variantpersonalpersonal or business.
business_nameCompany name injected into business system prompt.
business_descriptionOne-line description of the organisation.
business_toneprofessionalprofessional | friendly | technical | concise.
llm_providerollamaollama | openai-compatible | nvidia-nim | anthropic | google | groq | cohere | mistral.
ollama_base_urlhttp://localhost:11434Ollama server URL.
ollama_modelqwen2.5:7bOllama chat model.
ollama_embed_modelnomic-embed-textOllama embedding model.
openai_base_urlhttps://api.openai.com/v1OpenAI-compatible base URL.
openai_api_keyAPI key for OpenAI-compatible provider.
openai_modelgpt-4o-miniModel name.
nvidia_nim_base_urlhttps://integrate.api.nvidia.com/v1NVIDIA NIM OpenAI-compatible base URL.
nvidia_nim_api_keyNVIDIA API key.
nvidia_nim_modelmeta/llama-3.1-8b-instructNVIDIA NIM model ID.
anthropic_api_keyAnthropic API key.
anthropic_modelclaude-sonnet-4-5Anthropic model ID.
google_api_keyGoogle AI Studio API key.
google_modelgemini-2.0-flashGemini model ID.
groq_api_keyGroq API key.
groq_modelllama-3.3-70b-versatileGroq model ID.
cohere_api_keyCohere API key.
cohere_modelcommand-r-plusCohere model ID.
mistral_api_keyMistral AI API key.
mistral_modelmistral-large-latestMistral model ID.
embedding_providerollamaollama or openai-compatible.
jwt_secretSigns per-user JWT tokens. Admin API uses Authorization: Bearer <jwt_secret>.
jwt_expiry_hours720JWT lifetime in hours (30 days default).
rate_limit_enabledfalseEnable sliding-window rate limiting.
rate_limit_per_minute60Max requests per user per 60-second window.
rate_limit_burst20Extra burst allowance on top of the per-minute limit.
telegram_bot_tokenTelegram Bot API token from @BotFather.
discord_bot_tokenDiscord bot token.
discord_public_keyDiscord app public key for interaction signature verification.
slack_bot_tokenSlack bot OAuth token (xoxb-...).
slack_signing_secretSlack app signing secret for request verification.
github_tokenGitHub Personal Access Token for API tools (list/create issues, PRs).
github_webhook_secretHMAC secret for verifying GitHub webhook payloads.
github_default_repoDefault owner/repo for tool calls when no repo is specified.
github_notify_slack_channelSlack channel ID to forward GitHub event summaries to.
github_notify_telegram_chat_idTelegram chat ID to forward GitHub event summaries to.
host127.0.0.1Backend bind address. 0.0.0.0 for LAN/Docker.
port8899Backend HTTP port.
user_namefriendYour name — used in the personal variant system prompt.
luna_nameL.U.N.A.Assistant display name.
spotify_client_idSpotify Developer app client ID.
spotify_client_secretSpotify Developer app client secret.
the_news_apiTheNewsAPI key for live news widget.
alpha_vantageAlpha Vantage key for extended market data.
weather_lat40.7128Latitude for Open-Meteo weather.
weather_lon-74.0060Longitude for Open-Meteo weather.
weather_cityNew YorkDisplay name for the weather widget.
weather_timezoneAmerica/New_YorkIANA timezone string.