> ## Documentation Index
> Fetch the complete documentation index at: https://safia.maximusolution.com/llms.txt
> Use this file to discover all available pages before exploring further.

# SAFIA Configuration: Environment Variables Reference

> A full reference for SAFIA's .env variables: required credentials, LLM providers, database backends, admin auth, and knowledge base configuration.

SAFIA is configured through a `.env` file created during `safia setup`. You can re-open that file at any time using the interactive editor, or edit it directly with a text editor. All variables below correspond to entries in `.env`.

```bash theme={null}
safia config
```

The sections below group every supported variable by function. Variables marked **required** must be set before SAFIA will start successfully.

***

## Required

These four variables are the minimum needed to run the bot.

| Variable             | Description                                                                          |
| -------------------- | ------------------------------------------------------------------------------------ |
| `TELEGRAM_BOT_TOKEN` | Your bot's token from [@BotFather](https://t.me/BotFather).                          |
| `LLM_PROVIDER`       | The LLM backend to use: `lunos`, `groq`, `openai`, or `custom`. Defaults to `lunos`. |
| `LLM_API_KEY`        | API key for the selected LLM provider.                                               |
| `DATABASE_URL`       | SQLAlchemy connection string. Defaults to `sqlite+aiosqlite:///data/safia.db`.       |

A minimal `.env` for getting started:

```ini theme={null}
TELEGRAM_BOT_TOKEN=your-telegram-bot-token
LLM_PROVIDER=lunos
LLM_API_KEY=your-api-key
DATABASE_URL=sqlite+aiosqlite:///data/safia.db
```

<Warning>
  Never commit your `.env` file to version control. It contains credentials that grant full access to your bot and LLM account.
</Warning>

***

## LLM Settings

SAFIA supports four LLM providers out of the box. Each provider's base URL is set automatically — you only need to supply `LLM_PROVIDER` and `LLM_API_KEY`.

| Variable       | Default                                    | Description                                                                                                 |
| -------------- | ------------------------------------------ | ----------------------------------------------------------------------------------------------------------- |
| `LLM_PROVIDER` | `lunos`                                    | Provider name: `lunos`, `groq`, `openai`, or `custom`.                                                      |
| `LLM_API_KEY`  | —                                          | API key for the selected provider.                                                                          |
| `LLM_MODEL`    | `openai/gpt-oss-120b`                      | Model identifier passed to the provider API.                                                                |
| `LLM_BASE_URL` | —                                          | Base URL for a custom OpenAI-compatible provider. Required only when `LLM_PROVIDER=custom`.                 |
| `VISION_MODEL` | `mistralai/mistral-small-3.2-24b-instruct` | Model used for receipt and document photo extraction. Uses the same provider and API key as the chat model. |

<Tabs>
  <Tab title="Lunos">
    ```ini theme={null}
    LLM_PROVIDER=lunos
    LLM_API_KEY=your-lunos-api-key
    LLM_MODEL=openai/gpt-oss-120b
    ```

    The Lunos base URL (`https://api.lunosrouter.com/v1`) is set automatically.
  </Tab>

  <Tab title="Groq">
    ```ini theme={null}
    LLM_PROVIDER=groq
    LLM_API_KEY=your-groq-api-key
    LLM_MODEL=llama-3.3-70b-versatile
    ```

    Groq also powers Whisper speech-to-text. The Groq base URL is set automatically.
  </Tab>

  <Tab title="OpenAI">
    ```ini theme={null}
    LLM_PROVIDER=openai
    LLM_API_KEY=your-openai-api-key
    LLM_MODEL=gpt-4o
    ```

    Uses the standard OpenAI API endpoint.
  </Tab>

  <Tab title="Custom (OpenAI-Compatible)">
    ```ini theme={null}
    LLM_PROVIDER=custom
    LLM_API_KEY=your-api-key
    LLM_BASE_URL=https://your-provider.example.com/v1
    LLM_MODEL=your-model-name
    ```

    Set `LLM_BASE_URL` to any endpoint that implements the OpenAI Chat Completions API.
  </Tab>
</Tabs>

<Note>
  Speech-to-text always uses Whisper via Groq, regardless of which LLM provider you select for chat. If you use a non-Groq LLM provider, set `GROQ_API_KEY` separately to enable voice message transcription.
</Note>

### Voice Transcription and Web Search

Two optional integrations expand what SAFIA can do:

| Variable            | Default | Description                                                                                                                 |
| ------------------- | ------- | --------------------------------------------------------------------------------------------------------------------------- |
| `GROQ_API_KEY`      | —       | Groq API key for Whisper voice transcription. Required if your `LLM_PROVIDER` is not `groq`.                                |
| `FIRECRAWL_API_KEY` | —       | API key from [firecrawl.dev](https://firecrawl.dev) for web search and article fetching. Leave empty to disable web search. |

```ini theme={null}
# Optional: enable voice messages when using a non-Groq LLM provider
GROQ_API_KEY=your-groq-api-key

# Optional: enable web search and article fetching
FIRECRAWL_API_KEY=your-firecrawl-api-key
```

***

## Database & Cache

SAFIA stores all financial data in a relational database. Chat history, price caches, and per-user rate limits run in an in-memory cache that is transparently persisted to SQLite, so state survives restarts without an external cache server.

| Variable        | Default                             | Description                                                                                                 |
| --------------- | ----------------------------------- | ----------------------------------------------------------------------------------------------------------- |
| `DATABASE_URL`  | `sqlite+aiosqlite:///data/safia.db` | SQLAlchemy async connection string. SQLite is zero-config; use a PostgreSQL URL for production deployments. |
| `CACHE_DB_PATH` | `data/cache.db`                     | SQLite file used to persist the in-memory cache (chat history, price caches, rate-limit counters).          |

**SQLite** (default) — no additional setup required. The database file is created automatically at `data/safia.db`.

**PostgreSQL** — swap `DATABASE_URL` with an asyncpg connection string:

```ini theme={null}
DATABASE_URL=postgresql+asyncpg://user:password@localhost:5432/safia
```

<Tip>
  SQLite is the recommended choice for personal use. Switch to PostgreSQL only if you plan to run SAFIA for multiple users concurrently or need point-in-time backups.
</Tip>

***

## Admin Dashboard

The admin dashboard runs at `http://127.0.0.1:5454` and provides usage metrics, a user registry, and knowledge base management. Protect it with HTTP Basic Auth before using it.

| Variable           | Default   | Description                                                                     |
| ------------------ | --------- | ------------------------------------------------------------------------------- |
| `ADMIN_USERNAME`   | *(empty)* | Username for HTTP Basic Auth on the dashboard.                                  |
| `ADMIN_PASSWORD`   | *(empty)* | Password for HTTP Basic Auth on the dashboard.                                  |
| `FLASK_SECRET_KEY` | *(empty)* | Secret key used by Flask for session signing. Set this to a long random string. |

```ini theme={null}
ADMIN_USERNAME=admin
ADMIN_PASSWORD=a-strong-password-here
FLASK_SECRET_KEY=replace-with-a-random-secret-string
```

<Warning>
  If `ADMIN_USERNAME` and `ADMIN_PASSWORD` are left empty, the dashboard is accessible without authentication. Always set these before exposing port 5454 beyond localhost.
</Warning>

***

## Knowledge Base

The knowledge base (RAG) lets you upload documents that SAFIA uses to ground its responses. Embeddings and vector storage run locally by default.

| Variable                 | Default                                                       | Description                                                               |
| ------------------------ | ------------------------------------------------------------- | ------------------------------------------------------------------------- |
| `QDRANT_PATH`            | `data/qdrant`                                                 | On-disk path for Qdrant vector storage. Used when no `QDRANT_URL` is set. |
| `QDRANT_URL`             | *(empty)*                                                     | URL of a remote Qdrant server. Overrides `QDRANT_PATH` when set.          |
| `QDRANT_API_KEY`         | *(empty)*                                                     | API key for an authenticated remote Qdrant instance.                      |
| `KB_MAX_UPLOAD_MB`       | `200`                                                         | Maximum file size (in MB) for knowledge base document uploads.            |
| `KB_CHUNK_WORDS`         | `450`                                                         | Number of words per document chunk when ingesting files.                  |
| `KB_CHUNK_OVERLAP_WORDS` | `70`                                                          | Word overlap between consecutive chunks to preserve context.              |
| `EMBEDDING_LOCAL`        | `true`                                                        | Set to `false` to use a remote embedding API instead of local ONNX.       |
| `EMBEDDING_LOCAL_MODEL`  | `sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2` | Local ONNX embedding model (\~120 MB, downloads once).                    |

**Optional: Remote Qdrant**

```ini theme={null}
QDRANT_URL=http://127.0.0.1:6333
QDRANT_API_KEY=your-qdrant-api-key
```

**Optional: Remote Embeddings**

```ini theme={null}
EMBEDDING_LOCAL=false
EMBEDDING_BASE_URL=https://openrouter.ai/api/v1
EMBEDDING_API_KEY=your-key
EMBEDDING_MODEL=openai/text-embedding-3-small
EMBEDDING_VECTOR_SIZE=1536
```

<Note>
  The local embedding model downloads automatically on first use and runs on CPU via ONNX Runtime. No GPU is required. Switching to remote embeddings is only necessary if your machine has very limited disk space or you want to use a higher-dimensional model.
</Note>

***

## Reminders

SAFIA can send scheduled reminders for price alerts, news digests, and portfolio summaries.

| Variable                     | Default | Description                                                             |
| ---------------------------- | ------- | ----------------------------------------------------------------------- |
| `REMINDER_ENABLED`           | `true`  | Set to `false` to disable all scheduled reminders globally.             |
| `REMINDER_MAX_PER_USER`      | `10`    | Maximum number of active reminders a single user can have at one time.  |
| `REMINDER_MAX_SENDS_PER_DAY` | `15`    | Maximum reminder messages sent to a user per day.                       |
| `REMINDER_TICK_SECONDS`      | `30`    | How often (in seconds) the reminder scheduler checks for due reminders. |

```ini theme={null}
REMINDER_ENABLED=true
REMINDER_MAX_PER_USER=10
REMINDER_MAX_SENDS_PER_DAY=15
```

***

## Rate Limiting

SAFIA enforces a daily message limit per user to manage LLM API costs.

| Variable              | Default | Description                                                                        |
| --------------------- | ------- | ---------------------------------------------------------------------------------- |
| `DAILY_MESSAGE_LIMIT` | `1000`  | Maximum number of bot messages a single user can send per day. Resets at midnight. |

```ini theme={null}
DAILY_MESSAGE_LIMIT=1000
```

<Tip>
  Increase `DAILY_MESSAGE_LIMIT` if you are the sole user of your SAFIA instance and want unrestricted access. Be mindful of your LLM provider's rate limits and billing when raising this value.
</Tip>
