# Environment Variables

Complete reference of all environment variables used by Monetarie PIX, organized by category.

## Prerequisites

- Access to the server or Kubernetes cluster where Monetarie PIX will be deployed
- Permission to create/edit ConfigMaps and Secrets in the `pix` namespace
- Basic knowledge of environment variables in Docker/K8s containers

## Configuration Precedence

Monetarie PIX uses the Elixir/Phoenix configuration system with the following precedence (highest priority first):

```mermaid
flowchart LR
    A["Environment Variables<br/>(highest priority)"] --> B["runtime.exs<br/>(runtime)"]
    B --> C["prod.exs / dev.exs<br/>(environment)"]
    C --> D["config.exs<br/>(base)"]
```

1. **Environment variables** -- always take highest priority
2. **`config/runtime.exs`** -- executed at runtime (including in releases)
3. **`config/prod.exs`** or **`config/dev.exs`** -- per-environment configuration
4. **`config/config.exs`** -- base shared configuration

::: warning IMPORTANT
In release mode (production), only `runtime.exs` is executed. Environment variables defined in this file are the only way to configure the system in production.
:::

## Database

| Variable | Default | Required | Description |
|----------|---------|----------|-------------|
| `DATABASE_URL` | -- | No* | Full PostgreSQL connection URL (`postgres://user:pass@host:port/db`). If set, overrides individual variables below |
| `DB_HOST` | `localhost` | Yes (prod) | PostgreSQL server address |
| `DB_PORT` | `5432` | No | PostgreSQL port |
| `DB_USER` | `postgres` | Yes (prod) | Database user |
| `DB_PASS` | `postgres` | Yes (prod) | Database password |
| `DB_NAME` | `monetarie` | No | Database name |
| `POOL_SIZE` | `250` | No | Connection pool size **per repository** |
| `DATABASE_SSL` | `false` | No | Enable SSL for database connections |
| `ECTO_IPV6` | `false` | No | Enable IPv6 for database connections |

::: tip POOL_SIZE
The default of 250 connections is **per repository**. With 4 repositories (Shared, Dict, SPI, Settlement), the total is `250 x 4 = 1000` connections per pod. With 2 pods, that is 2,000 connections. Cloud SQL must have `max_connections >= 2200`.
:::

::: danger SPECIAL CHARACTERS IN PASSWORDS
If the database password contains special characters, use URL encoding in `DATABASE_URL`:
- `/` -> `%2F`
- `=` -> `%3D`
- `@` -> `%40`
- `#` -> `%23`
:::

## Redis

| Variable | Default | Required | Description |
|----------|---------|----------|-------------|
| `REDIS_HOST` | `localhost` | Yes (prod) | Redis server address |
| `REDIS_PORT` | `6379` | No | Redis port |

## NATS JetStream

| Variable | Default | Required | Description |
|----------|---------|----------|-------------|
| `NATS_HOST` | `localhost` | Yes (prod) | NATS server address |
| `NATS_PORT` | `4222` | No | NATS port |
| `NATS_USER` | -- | No | NATS authentication user |
| `NATS_PASS` | -- | No | NATS authentication password |
| `NATS_ENABLED` | `false` | No | Enable NATS JetStream workers. Set to `true` in production |

::: warning NATS_ENABLED
NATS workers are disabled by default. In production, set `NATS_ENABLED=true` to activate SPI workers (InboundProcessor, OutboundSender, StatusUpdater, ReturnProcessor) and CoreEventProcessor.
:::

## Authentication and Security

| Variable | Default | Required | Description |
|----------|---------|----------|-------------|
| `SECRET_KEY_BASE` | -- | **Yes** | Phoenix secret key for cookies and sessions. Generate with `mix phx.gen.secret` |
| `JWT_SECRET` | -- | No | JWT signing key. Fallback: `GUARDIAN_SECRET_KEY` -> `SECRET_KEY_BASE` |
| `GUARDIAN_SECRET_KEY` | -- | No | Shared key with Core Banking (Guardian HS256). Required for Core integration |

The JWT secret fallback chain:

```
JWT_SECRET  -->  GUARDIAN_SECRET_KEY  -->  SECRET_KEY_BASE
```

::: tip LOCAL DEVELOPMENT WITH CORE
For local integration testing with Core Banking, set `JWT_SECRET` to `"dev-only-secret-key-not-for-production"` (Core's development secret).
:::

## BACEN (Central Bank)

| Variable | Default | Required | Description |
|----------|---------|----------|-------------|
| `BACEN_ENV` | `homolog` | No | BACEN environment: `homolog` or `production` |
| `BACEN_ENABLED` | `false` | No | Enable real BACEN integration via RSFN |
| `BACEN_ISPB` | `00000000` | Yes (prod) | Institution's ISPB code (8 digits) |
| `BACEN_PARTICIPANT_NAME` | `MONETARIE` | No | Short participant name |
| `BACEN_CNPJ` | -- | Yes (prod) | Institution's CNPJ |
| `BACEN_CA_CERT_PATH` | -- | Yes (prod) | Path to BACEN root CA certificate |
| `BACEN_CLIENT_CERT_PATH` | -- | Yes (prod) | Path to ICP-Brasil institution certificate (CPIC) |
| `BACEN_CLIENT_KEY_PATH` | -- | Yes (prod) | Path to certificate private key |
| `BACEN_CLIENT_KEY_PASSWORD` | -- | No | Private key password (if encrypted) |
| `BACEN_TIMEOUT` | `30000` | No | BACEN connection timeout in milliseconds |
| `BACEN_FAILOVER_ENABLED` | `true` | No | Enable automatic failover between CPM/CSM channels |
| `BACEN_FAILURE_THRESHOLD` | `3` | No | Consecutive failures before marking channel as inactive |
| `BACEN_HEALTH_CHECK_INTERVAL` | `30` | No | Channel health check interval (seconds) |

## Simulator

| Variable | Default | Required | Description |
|----------|---------|----------|-------------|
| `SIMULATOR_ENABLED` | `false` | No | Enable BACEN PIX simulator. Do not use in production |

::: danger SIMULATOR IN PRODUCTION
**Never** enable `SIMULATOR_ENABLED=true` in production. The simulator overrides real BACEN communication behavior.
:::

## Internal Services

| Variable | Default | Required | Description |
|----------|---------|----------|-------------|
| `DICT_SERVICE_URL` | `http://localhost:4001` | No | Internal DICT service URL (used by CoreEventProcessor) |
| `SPI_SERVICE_URL` | `http://localhost:4002` | No | Internal SPI service URL |
| `DICT_HOST` | `localhost` | No | DICT endpoint host |
| `DICT_PORT` | `4001` | No | DICT endpoint port |
| `SPI_HOST` | `localhost` | No | SPI endpoint host |
| `SPI_PORT` | `4002` | No | SPI endpoint port |
| `SETTLEMENT_HOST` | `localhost` | No | Settlement (API gateway) endpoint host |
| `SETTLEMENT_PORT` | `4003` | No | Settlement (API gateway) endpoint port |

## Application

| Variable | Default | Required | Description |
|----------|---------|----------|-------------|
| `PHX_HOST` | -- | No | Public hostname for URL generation |
| `PHX_PORT` | `443` | No | Public port (HTTPS) |
| `MIX_ENV` | `dev` | Yes (prod) | Elixir environment: `dev`, `test`, or `prod` |
| `RELEASE_NAME` | `monetarie_pix` | No | Elixir release name |

## Complete Production Example

```bash
# === Database ===
export DB_HOST="10.140.241.2"
export DB_PORT="5432"
export DB_USER="monetarie_prod"
export DB_PASS="SecurePassword123"
export DB_NAME="monetarie"
export POOL_SIZE="250"

# === Redis ===
export REDIS_HOST="10.140.240.4"
export REDIS_PORT="6379"

# === NATS ===
export NATS_HOST="10.10.40.5"
export NATS_PORT="4222"
export NATS_ENABLED="true"

# === Authentication ===
export SECRET_KEY_BASE="$(mix phx.gen.secret)"
export GUARDIAN_SECRET_KEY="shared-key-with-core"

# === BACEN ===
export BACEN_ENV="homolog"
export BACEN_ENABLED="true"
export BACEN_ISPB="12345678"
export BACEN_CNPJ="12345678000199"
export BACEN_CA_CERT_PATH="/certs/bacen-ca.pem"
export BACEN_CLIENT_CERT_PATH="/certs/cpic.pem"
export BACEN_CLIENT_KEY_PATH="/certs/cpic-key.pem"

# === Services ===
export DICT_SERVICE_URL="http://localhost:4001"
export SPI_SERVICE_URL="http://localhost:4002"
```

## Kubernetes Configuration (Secrets)

In Kubernetes, secrets are stored in Secret objects with **kebab-case** keys:

```yaml
apiVersion: v1
kind: Secret
metadata:
  name: db-credentials
  namespace: pix
type: Opaque
stringData:
  database-url: "postgres://monetarie_prod:SecurePassword@10.140.241.2:5432/monetarie"
  secret-key-base: "your-secret-key-here"
```

```yaml
apiVersion: v1
kind: Secret
metadata:
  name: monetarie-shared-jwt-secret
  namespace: pix
type: Opaque
stringData:
  jwt-secret: "shared-key-with-core-banking"
```

::: warning KEBAB-CASE KEYS
Kubernetes Secret keys use **kebab-case** (`database-url`, `secret-key-base`), NOT SCREAMING_SNAKE_CASE. The `backend.yaml` maps these to the correct environment variables.
:::

## Secret Management

### Recommendations

1. **Never** store secrets in version-controlled configuration files
2. Use **K8s Secrets** for Kubernetes environments
3. For enterprise environments, consider:
   - **HashiCorp Vault** with the Kubernetes operator
   - **GCP Secret Manager** with workload identity
   - **AWS Secrets Manager** with IRSA
4. Rotate `SECRET_KEY_BASE` and `GUARDIAN_SECRET_KEY` periodically
5. Use strong database passwords (minimum 32 characters, alphanumeric + special)

### Configuration Verification

After setting all variables, verify the configuration:

```bash
# In development
cd backend
mix phx.server

# In Kubernetes (check pod logs)
kubectl logs -n pix deployment/pix-backend --tail=50

# Check that all services started
# Look for: "=== Starting Shared Application ===" in logs
```

## Expected Outcome

After configuring all required variables:

- The backend starts without errors, displaying `"=== Starting Shared Application (postgrex 0.16.x) ==="` in logs
- All 4 HTTP endpoints respond (DICT:4001, SPI:4002, Settlement:4003)
- If `NATS_ENABLED=true`, the SPI workers and CoreEventProcessor are active
- If `BACEN_ENABLED=true`, the mTLS connection with BACEN is established
- The health check at `GET /health` returns status 200
