Skip to main content

Environment variables

SKU Semantic Search uses environment variables for all configuration. This follows the 12-factor app methodology for portable, secure deployments.

Configuration file

Create a .env file in the project root with the following variables:
# Application metadata
PROJECT_NAME="SKU Semantic Search"
VERSION="1.0.0"

# Database configuration
DATABASE_URL="postgresql://postgres:db_pass@localhost:5435/retail_rag"

# AI provider API keys
GEMINI_API_KEY="your_gemini_api_key_here"
ANTHROPIC_API_KEY="your_anthropic_api_key_here"

# JWT authentication
JWT_SECRET="your_very_secure_random_secret_key"
ALGORITHM="HS256"
ACCESS_TOKEN_EXPIRE_MINUTES=30
Never commit your .env file to version control. Add it to .gitignore to prevent accidentally exposing secrets.

Configuration reference

Application settings

PROJECT_NAME
string
default:"SKU Semantic Search"
Application name displayed in API documentation and responses.
VERSION
string
default:"1.0.0"
API version number, displayed in FastAPI docs.

Database settings

DATABASE_URL
string
required
PostgreSQL connection string in the format:
postgresql://[user]:[password]@[host]:[port]/[database]
Examples:
# Local development
DATABASE_URL="postgresql://postgres:db_pass@localhost:5435/retail_rag"

# Docker Compose (container-to-container)
DATABASE_URL="postgresql://postgres:db_pass@db:5432/retail_rag"

# Production with SSL
DATABASE_URL="postgresql://user:[email protected]:5432/sku_prod?sslmode=require"
The Docker Compose configuration uses port 5435 externally but 5432 internally to avoid conflicts with local PostgreSQL installations.

AI provider settings

GEMINI_API_KEY
string
required
Google Gemini API key for embeddings and text generation.How to get:
  1. Visit Google AI Studio
  2. Sign in with your Google account
  3. Click “Get API key”
  4. Copy the key (starts with AI...)
Free tier limits:
  • 60 requests per minute
  • Generous monthly quota for experimentation
Test your key using:
curl "https://generativelanguage.googleapis.com/v1beta/models?key=YOUR_KEY"
ANTHROPIC_API_KEY
string
required
Anthropic Claude API key for failover text generation.How to get:
  1. Visit Anthropic Console
  2. Sign up or sign in
  3. Navigate to API Keys
  4. Generate a new key (starts with sk-ant-...)
Free tier: Anthropic provides $5 in free credits for testing.
While optional for basic operation, this key is essential for high availability. The system falls back to Claude when Gemini is unavailable.

Authentication settings

JWT_SECRET
string
required
Secret key for signing JWT tokens. Must be a strong, random string.Generate a secure secret:
# Linux/macOS
openssl rand -hex 32

# Python
python -c "import secrets; print(secrets.token_hex(32))"

# Output example:
# 5f8d3e9a7b2c1f4e6d8a9b3c5e7f1a4d6b8c9e2f4a5b7c9d1e3f5a7b9c1d3e5f
Use a unique, random secret for each environment. Never reuse secrets between development, staging, and production.
ALGORITHM
string
default:"HS256"
JWT signing algorithm. HS256 (HMAC with SHA-256) is recommended for symmetric key signing.Other options: HS384, HS512, RS256 (requires RSA keys)
ACCESS_TOKEN_EXPIRE_MINUTES
integer
default:"30"
JWT token expiration time in minutes.Recommendations:
  • Development: 60-480 minutes (longer sessions for testing)
  • Production: 15-30 minutes (better security)
  • Long-lived API tokens: Consider refresh tokens for extended access

Loading configuration

The application loads environment variables using Pydantic Settings (app/core/config.py:3):
from pydantic_settings import BaseSettings

class Settings(BaseSettings):
    PROJECT_NAME: str = "SKU Semantic Search"
    VERSION: str = "1.0.0"
    
    # Database and security
    DATABASE_URL: str
    GEMINI_API_KEY: str
    ANTHROPIC_API_KEY: str
    JWT_SECRET: str
    ALGORITHM: str = "HS256"
    ACCESS_TOKEN_EXPIRE_MINUTES: int = 30

    class Config:
        env_file = ".env"
        env_file_encoding = 'utf-8'

# Instantiate settings for use throughout the app
settings = Settings()
Key features:
  • Type validation: Pydantic ensures variables have correct types
  • Required fields: Raises errors if required variables are missing
  • Default values: Falls back to defaults for optional settings
  • Auto-loading: Automatically reads from .env file

Environment-specific configuration

For multiple environments, use separate .env files:
.env.development
PROJECT_NAME="SKU Search (Dev)"
DATABASE_URL="postgresql://postgres:dev_pass@localhost:5435/retail_rag_dev"
GEMINI_API_KEY="AI..."
ANTHROPIC_API_KEY="sk-ant-..."
JWT_SECRET="dev_secret_not_for_production"
ACCESS_TOKEN_EXPIRE_MINUTES=480
Load with:
ln -sf .env.development .env
# or
cp .env.development .env

Verifying configuration

To check if your environment is correctly configured:
1

Verify .env file exists

cat .env
Ensure all required variables are present and have values (not placeholders like your_key_here).
2

Test database connection

python -c "from app.db.session import engine; print(engine.url)"
Should print your database URL.
3

Validate API keys

python -c "from app.core.config import settings; print('Gemini:', settings.GEMINI_API_KEY[:10], '...'); print('Anthropic:', settings.ANTHROPIC_API_KEY[:10], '...')"
Should print truncated keys (not placeholders).
4

Start the application

uvicorn app.main:app --reload
If configuration is correct, you’ll see:
INFO:     Started server process [12345]
INFO:     Waiting for application startup.
INFO:     Application startup complete.

Security best practices

Rotate API keys regularly:
  1. Generate new key from provider console
  2. Update .env file
  3. Restart the application
  4. Delete old key from provider
Recommended frequency:
  • Development: Every 90 days
  • Production: Every 30-60 days
For production, use dedicated secret management:
  • AWS: Secrets Manager, Parameter Store
  • GCP: Secret Manager
  • Azure: Key Vault
  • HashiCorp: Vault
  • Kubernetes: Secrets
Example with AWS Secrets Manager:
import boto3

def get_secret(secret_name):
    client = boto3.client('secretsmanager')
    response = client.get_secret_value(SecretId=secret_name)
    return response['SecretString']

settings.GEMINI_API_KEY = get_secret('prod/gemini-api-key')
In containerized environments, inject secrets at runtime:
# Docker run
docker run -e GEMINI_API_KEY=$GEMINI_API_KEY app

# Kubernetes
kubectl create secret generic api-keys \
  --from-literal=gemini-key=$GEMINI_API_KEY
This avoids storing secrets in images.
Restrict who can access secrets:
  • Use IAM roles for cloud secrets
  • Implement RBAC for Kubernetes secrets
  • Limit file permissions: chmod 600 .env
  • Use separate keys per environment/team

Troubleshooting

Cause: Required environment variable is missingSolution:
  1. Check .env file exists in project root
  2. Verify variable name matches exactly (case-sensitive)
  3. Ensure no quotes around variable names: GEMINI_API_KEY=value, not "GEMINI_API_KEY"=value
Cause: Invalid API key or expired free tierSolution:
  1. Regenerate API key from provider console
  2. Check for leading/trailing whitespace in .env
  3. Verify key hasn’t been revoked
  4. Check billing status if using paid tier
Cause: Incorrect DATABASE_URL or PostgreSQL not runningSolution:
  1. Verify PostgreSQL is running: docker ps
  2. Check port matches Docker Compose config (5435 external)
  3. For Docker, use service name db as host, not localhost
  4. Test connection: psql $DATABASE_URL
Cause: Pydantic can’t find .env fileSolution:
  1. Ensure .env is in project root (same directory as app/)
  2. Check file is named exactly .env (not .env.txt)
  3. Verify UTF-8 encoding: file .env should show UTF-8
  4. Try absolute path in Config: env_file = "/path/to/.env"

Next steps

Database setup

Configure PostgreSQL with pgvector

Docker deployment

Deploy using Docker Compose

Multi-LLM failover

Configure multiple AI providers

Installation

Complete installation guide

Build docs developers (and LLMs) love