# On-Premises Deployment

Deploy Monetarie PIX on bare metal or virtualized infrastructure for regulated environments requiring full data sovereignty.

## Prerequisites

- Virtualization platform (ProxMox, VMware, Hyper-V) or bare metal servers
- Network infrastructure with firewall capabilities
- Load balancer (HAProxy, nginx, or hardware LB)
- Access to ICP-Brasil certificates for BACEN connectivity

## Reference Architecture

```mermaid
graph TB
    INET[Internet] --> FW[Firewall]
    FW --> HAP[HAProxy<br/>TLS Termination]
    HAP --> APP1[App Server 1<br/>Monetarie PIX]
    HAP --> APP2[App Server 2<br/>Monetarie PIX]

    APP1 --> PG_P[(PostgreSQL Primary)]
    APP2 --> PG_P
    PG_P --> PG_R[(PostgreSQL Replica)]

    APP1 --> REDIS[Redis Sentinel<br/>3 nodes]
    APP2 --> REDIS

    APP1 --> NATS1[NATS Node 1]
    APP2 --> NATS2[NATS Node 2]
    NATS1 --> NATS3[NATS Node 3]
```

## Hardware Requirements

| Role | CPU | RAM | Disk | Qty |
|------|-----|-----|------|-----|
| Application Server | 8 cores | 32 GB | 100 GB SSD | 2 |
| PostgreSQL Primary | 8 cores | 64 GB | 1 TB NVMe | 1 |
| PostgreSQL Replica | 8 cores | 64 GB | 1 TB NVMe | 1 |
| Redis Sentinel | 4 cores | 8 GB | 50 GB SSD | 3 |
| NATS Server | 4 cores | 16 GB | 200 GB SSD | 3 |
| HAProxy | 4 cores | 8 GB | 50 GB SSD | 2 |

## VM Setup (ProxMox Example)

### Create VMs

```bash
# Application servers
qm create 101 --name pix-app-1 --cores 8 --memory 32768 --net0 virtio,bridge=vmbr0
qm create 102 --name pix-app-2 --cores 8 --memory 32768 --net0 virtio,bridge=vmbr0

# PostgreSQL
qm create 201 --name pix-db-primary --cores 8 --memory 65536 --net0 virtio,bridge=vmbr0
qm create 202 --name pix-db-replica --cores 8 --memory 65536 --net0 virtio,bridge=vmbr0
```

### Install Dependencies (Ubuntu 22.04)

```bash
# Docker
curl -fsSL https://get.docker.com | sh

# Or install Elixir directly for systemd deployment
wget https://packages.erlang-solutions.com/erlang-solutions_2.0_all.deb
dpkg -i erlang-solutions_2.0_all.deb
apt-get update && apt-get install -y esl-erlang elixir
```

## PostgreSQL with Patroni

```yaml
# patroni.yml
scope: monetarie-pix
namespace: /service/
name: node1

restapi:
  listen: 0.0.0.0:8008

postgresql:
  listen: 0.0.0.0:5432
  data_dir: /var/lib/postgresql/16/main
  parameters:
    max_connections: 6000
    shared_buffers: 16GB
    effective_cache_size: 48GB
    work_mem: 64MB
```

## Redis Sentinel

```conf
# sentinel.conf (on each of 3 nodes)
sentinel monitor monetarie-pix-redis 10.0.1.10 6379 2
sentinel down-after-milliseconds monetarie-pix-redis 5000
sentinel failover-timeout monetarie-pix-redis 60000
```

## NATS Cluster

```conf
# nats-server.conf (per node)
port: 4222
jetstream {
    store_dir: /data/nats
    max_mem: 4G
    max_file: 100G
}
cluster {
    name: monetarie-pix
    listen: 0.0.0.0:6222
    routes: [
        nats://10.0.2.1:6222
        nats://10.0.2.2:6222
        nats://10.0.2.3:6222
    ]
}
```

## Application Deployment (Systemd)

### Build Release

```bash
cd backend
MIX_ENV=prod mix deps.get
MIX_ENV=prod mix release
```

### Systemd Unit

```ini
# /etc/systemd/system/monetarie-pix.service
[Unit]
Description=Monetarie PIX Backend
After=network.target postgresql.service

[Service]
Type=exec
User=monetarie
Group=monetarie
WorkingDirectory=/opt/monetarie/pix
ExecStart=/opt/monetarie/pix/bin/monetarie_pix start
ExecStop=/opt/monetarie/pix/bin/monetarie_pix stop
Restart=on-failure
RestartSec=5
EnvironmentFile=/opt/monetarie/pix/.env
LimitNOFILE=65536

[Install]
WantedBy=multi-user.target
```

```bash
systemctl enable monetarie-pix
systemctl start monetarie-pix
```

## HAProxy Configuration

```conf
frontend https_frontend
    bind *:443 ssl crt /etc/haproxy/certs/monetarie.pem
    default_backend pix_backend

backend pix_backend
    balance roundrobin
    option httpchk GET /health
    http-check expect status 200
    server app1 10.0.1.1:4003 check inter 5s fall 3 rise 2
    server app2 10.0.1.2:4003 check inter 5s fall 3 rise 2
```

## Firewall Rules

```bash
# Allow HTTPS inbound
iptables -A INPUT -p tcp --dport 443 -j ACCEPT

# Allow internal services
iptables -A INPUT -s 10.0.0.0/8 -p tcp --dport 4001:4003 -j ACCEPT
iptables -A INPUT -s 10.0.0.0/8 -p tcp --dport 5432 -j ACCEPT
iptables -A INPUT -s 10.0.0.0/8 -p tcp --dport 6379 -j ACCEPT
iptables -A INPUT -s 10.0.0.0/8 -p tcp --dport 4222 -j ACCEPT

# Allow BACEN outbound
iptables -A OUTPUT -p tcp --dport 16522 -j ACCEPT
iptables -A OUTPUT -p tcp --dport 17522 -j ACCEPT
```

## Expected Outcome

After completing this deployment:

- 2 application servers behind HAProxy with health-checked load balancing
- PostgreSQL primary-replica with automatic failover via Patroni
- Redis Sentinel for cache HA
- NATS 3-node JetStream cluster
- All traffic encrypted with TLS
- Firewall restricting access to required ports only
