# Environment Variables Reference

## Overview

This document describes all environment variables used by Headquarter. Variables are categorized by component and purpose.

## Required Variables

These variables must be set for the application to function:

### Domains

| Variable | Default | Description |
|----------|---------|-------------|
| `API_DOMAIN` | `localhost` | API server domain (e.g., `api.example.com`) |
| `WEB_DOMAIN` | `localhost` | Web frontend domain (e.g., `app.example.com`) |

### Database

| Variable | Default | Description |
|----------|---------|-------------|
| `POSTGRES_USER` | `headquarter` | PostgreSQL username |
| `POSTGRES_PASSWORD` | `headquarter` | PostgreSQL password (change in production!) |
| `POSTGRES_DB` | `headquarter` | PostgreSQL database name |

### Authentication

| Variable | Default | Description |
|----------|---------|-------------|
| `AUTHENTIK_DOMAIN` | `authentik.local` | Authentik server domain |
| `AUTHENTIK_CLIENT_ID` | `headquarter-web` | OAuth client ID from Authentik |
| `AUTHENTIK_CLIENT_SECRET` | `change-me` | OAuth client secret (change immediately!) |
| `AUTHENTIK_APPLICATION_SLUG` | `headquarter-web` | Authentik application slug |
| `SESSION_SECRET` | `change-me-session-secret` | Secret for signing session cookies (min 32 chars) |

## Optional Variables

### Application

| Variable | Default | Description |
|----------|---------|-------------|
| `APP_ENV` | `development` | Environment: `development`, `staging`, `production` |
| `LOG_LEVEL` | `INFO` | Logging level: `DEBUG`, `INFO`, `WARNING`, `ERROR` |

### Database

| Variable | Default | Description |
|----------|---------|-------------|
| `DATABASE_URL` | (constructed) | Full PostgreSQL connection URL |
| `POSTGRES_HOST` | `postgres` | PostgreSQL hostname |
| `POSTGRES_PORT` | `5432` | PostgreSQL port |

When `DATABASE_URL` is not set, it's constructed from:
```
postgresql+asyncpg://POSTGRES_USER:POSTGRES_PASSWORD@POSTGRES_HOST:POSTGRES_PORT/POSTGRES_DB
```

### URLs

| Variable | Default | Description |
|----------|---------|-------------|
| `API_PUBLIC_URL` | (constructed) | Public API URL (e.g., `https://api.example.com`) |
| `WEB_PUBLIC_URL` | (constructed) | Public web URL (e.g., `https://app.example.com`) |

Constructed from domains when not set:
```
API: https://API_DOMAIN (production) or http://API_DOMAIN:8000 (development)
WEB: https://WEB_DOMAIN (production) or http://WEB_DOMAIN:5173 (development)
```

### Authentik Overrides

| Variable | Default | Description |
|----------|---------|-------------|
| `AUTHENTIK_AUTHORIZE_URL` | (constructed) | OAuth authorization endpoint |
| `AUTHENTIK_TOKEN_URL` | (constructed) | OAuth token endpoint |
| `AUTHENTIK_JWKS_URL` | (constructed) | JWKS endpoint |
| `AUTHENTIK_ISSUER` | (constructed) | OAuth issuer URL |
| `AUTHENTIK_AUDIENCE` | `headquarter-web` | Token audience |

Constructed URLs:
```
https://AUTHENTIK_DOMAIN/application/o/authorize/
https://AUTHENTIK_DOMAIN/application/o/token/
https://AUTHENTIK_DOMAIN/application/o/AUTHENTIK_APPLICATION_SLUG/jwks/
https://AUTHENTIK_DOMAIN/application/o/AUTHENTIK_APPLICATION_SLUG/
```

### Session

| Variable | Default | Description |
|----------|---------|-------------|
| `SESSION_TTL_HOURS` | `24` | Session cookie lifetime in hours |
| `COOKIE_DOMAIN` | (none) | Cookie domain (set for cross-subdomain) |
| `COOKIE_SECURE` | `true` (prod) | Secure cookie flag |
| `COOKIE_SAMESITE` | `lax` | SameSite cookie attribute |

### Storage

| Variable | Default | Description |
|----------|---------|-------------|
| `REPO_BASE_PATH` | `/data/repos` | Base path for git repositories |
| `UPLOAD_DIR` | `uploads` | Directory for file uploads |

### Development

| Variable | Default | Description |
|----------|---------|-------------|
| `VITE_API_BASE_URL` | `http://localhost:8000` | Frontend API URL |

## Docker Compose Variables

### Traefik

| Variable | Default | Description |
|----------|---------|-------------|
| `TRAEFIK_NETWORK` | `traefik` | Docker network name for Traefik |
| `TRAEFIK_CERT_RESOLVER` | `letsencrypt` | Certificate resolver name |

### Docker Specific

| Variable | Default | Description |
|----------|---------|-------------|
| `COMPOSE_PROJECT_NAME` | `headquarter` | Docker Compose project name |

## Configuration Examples

### Development

```bash
APP_ENV=development
API_DOMAIN=localhost
WEB_DOMAIN=localhost
DATABASE_URL=postgresql+asyncpg://headquarter:headquarter@localhost:5432/headquarter
AUTHENTIK_DOMAIN=authentik.local
AUTHENTIK_CLIENT_ID=headquarter-web
AUTHENTIK_CLIENT_SECRET=dev-secret
SESSION_SECRET=dev-session-secret-change-in-production
VITE_API_BASE_URL=http://localhost:8000
```

### Production

```bash
APP_ENV=production
API_DOMAIN=api.headquarter.example.com
WEB_DOMAIN=app.headquarter.example.com
POSTGRES_PASSWORD=very-secure-password-here
AUTHENTIK_DOMAIN=auth.example.com
AUTHENTIK_CLIENT_ID=your-uuid-from-authentik
AUTHENTIK_CLIENT_SECRET=your-secret-from-authentik
AUTHENTIK_APPLICATION_SLUG=headquarter-web
SESSION_SECRET=minimum-32-characters-long-secret-key
SESSION_TTL_HOURS=24
COOKIE_DOMAIN=.headquarter.example.com
TRAEFIK_NETWORK=web
TRAEFIK_CERT_RESOLVER=letsencrypt
REPO_BASE_PATH=/data/repos
```

### Testing

```bash
APP_ENV=testing
DATABASE_URL=postgresql+asyncpg://headquarter:headquarter@localhost:5432/headquarter_test
SESSION_SECRET=test-secret
AUTHENTIK_CLIENT_ID=test-client
AUTHENTIK_CLIENT_SECRET=test-secret
```

## Security Checklist

Before deploying to production, verify:

- [ ] `POSTGRES_PASSWORD` is strong and unique
- [ ] `AUTHENTIK_CLIENT_SECRET` is kept secret
- [ ] `SESSION_SECRET` is at least 32 characters
- [ ] `APP_ENV` is set to `production`
- [ ] `COOKIE_SECURE` is enabled
- [ ] `COOKIE_DOMAIN` is set for your domain
- [ ] No default secrets in production
- [ ] `.env` file is not committed to git
- [ ] `.env` file has restricted permissions (600)

## Troubleshooting

### Variable Not Set

```bash
# Error: "Environment variable not set"
# Solution: Export the variable or add to .env file
export SESSION_SECRET="your-secret-here"
```

### Invalid URL

```bash
# Error: "Invalid URL"
# Solution: Check domain variables don't include protocol
# Bad: API_DOMAIN=https://api.example.com
# Good: API_DOMAIN=api.example.com
```

### Database Connection Failed

```bash
# Check DATABASE_URL or individual components
# Verify PostgreSQL is running
# Check credentials match
```

## Migration from Old Config

If upgrading from older versions:

1. `JWT_SECRET` → Removed (not needed with session auth)
2. `ACCESS_TOKEN_TTL_MINUTES` → Removed
3. `REFRESH_TOKEN_TTL_DAYS` → Removed
4. `AUTHENTIK_AUDIENCE` → Now defaults to `AUTHENTIK_CLIENT_ID`
5. `AUTHENTIK_APPLICATION_SLUG` → New variable for URL construction

## Environment Files

### Files Structure

```
headquarter/
├── .env                    # Main environment (not committed)
├── .env.example            # Example/template
├── apps/
│   ├── api/
│   │   └── .env           # API-specific overrides
│   └── web/
│       └── .env           # Frontend-specific overrides
└── docker-compose.traefik.yml  # References .env
```

### Loading Order

1. System environment variables
2. `.env` file in project root
3. Component-specific `.env` files
4. Default values in code

Later values override earlier ones.

## Validation

The application validates required variables on startup:

```python
# Missing critical variable
if not settings.session_secret or settings.session_secret == "change-me":
    logger.warning("SESSION_SECRET not configured properly!")

# Invalid configuration
if settings.app_env == "production" and "localhost" in settings.api_domain:
    logger.warning("Using localhost in production!")
```

## Best Practices

1. **Never commit `.env` files**
2. **Use strong passwords** for database and secrets
3. **Rotate secrets** regularly
4. **Use different secrets** per environment
5. **Document custom variables** in this file
6. **Validate configuration** before deployment
