# Deploy — melhorprecodf.com.br (Ubuntu 24.04)

Checklist operacional para recriar o stack no servidor LAMP + Certbot.
O site Django fica em `/var/www/html/melhorprecodf.com.br`. Credenciais
(VPN PSK, senhas L2TP, `caixa.json`) **nunca** entram no git.

Ordem: bootstrap → deploy GitHub → Apache → worker/Xvfb → VPN/Squid → Chrome/Selenium.

---

## Pré-requisitos no servidor

- Ubuntu 24.04, Apache, MySQL, Certbot já instalados
- Banco `melhorprecodf` importado (user `melhorprecodf` @ `127.0.0.1`)
- DNS `melhorprecodf.com.br` apontando para o IP do servidor
- Pacotes úteis:

```bash
sudo apt update
sudo apt install -y python3.12 python3.12-venv python3.12-dev \
  default-libmysqlclient-dev pkg-config build-essential \
  libapache2-mod-wsgi-py3 xvfb \
  strongswan xl2tpd ppp squid \
  curl wget gnupg
```

---

## Bootstrap inicial do código (uma vez)

Antes do primeiro GitHub Actions funcionar:

```bash
sudo mkdir -p /var/www/html/melhorprecodf.com.br /var/log/melhorpreco
sudo chown ubuntu:www-data /var/www/html/melhorprecodf.com.br
sudo chmod 775 /var/www/html/melhorprecodf.com.br

# Opção A: clone
cd /var/www/html
git clone git@github.com:SEU_ORG/melhorpreco_site.git melhorprecodf.com.br

# Opção B: rsync manual do seu PC para o path acima

cd /var/www/html/melhorprecodf.com.br
python3.12 -m venv venv_3_12
./venv_3_12/bin/pip install --upgrade pip
./venv_3_12/bin/pip install -r requirements.txt

mkdir -p chrome_temp downloaded_files staticfiles
sudo chown -R ubuntu:www-data .
sudo chown -R www-data:www-data chrome_temp downloaded_files /var/log/melhorpreco
sudo chmod 775 chrome_temp downloaded_files

./venv_3_12/bin/python manage.py migrate --noinput
./venv_3_12/bin/python manage.py collectstatic --noinput
./venv_3_12/bin/python manage.py check
```

Confirme permissões do env de produção (lido por `core/settings.py`):

```bash
sudo chown ubuntu:www-data /etc/melhorprecodf/django.env
sudo chmod 640 /etc/melhorprecodf/django.env
# Deve conter DB_NAME, DB_USER, DB_PASSWORD (e opcionalmente DB_HOST, DB_PORT)
```

---

## Fase 1 — Deploy GitHub (chave SSH dedicada)

Mesmo host do Drupal, **outra chave** (não reutilize a do `danielcatao.com.br`).

### No servidor (usuário `ubuntu`)

```bash
ssh-keygen -t ed25519 -f ~/.ssh/melhorpreco_deploy -N "" -C "melhorpreco-gha-deploy"
cat ~/.ssh/melhorpreco_deploy.pub >> ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys ~/.ssh/melhorpreco_deploy
chmod 644 ~/.ssh/melhorpreco_deploy.pub

# Teste local da chave
ssh -i ~/.ssh/melhorpreco_deploy -p PORTA ubuntu@127.0.0.1 'echo ok'
```

Garanta que `ubuntu` pode:

- escrever em `/var/www/html/melhorprecodf.com.br` (owner `ubuntu:www-data`)
- rodar `sudo chown`, `sudo systemctl reload apache2` (como no Drupal)

Exiba a **privada** só para colar no GitHub (não deixe cópia em lugares inseguros):

```bash
cat ~/.ssh/melhorpreco_deploy
```

### No GitHub → repo `melhorpreco_site` → Settings → Secrets and variables → Actions

| Secret | Valor |
|--------|--------|
| `SSH_HOST` | IP ou DNS do servidor |
| `SSH_USER` | `ubuntu` |
| `SSH_PORT` | porta SSH |
| `SSH_PRIVATE_KEY` | conteúdo completo de `~/.ssh/melhorpreco_deploy` |

O workflow está em [`.github/workflows/deploy.yml`](../.github/workflows/deploy.yml):

- dispara em `push` na `dev` (branch padrão do repo) ou `workflow_dispatch`
- rsync com excludes de `venv_3_12`, `chrome_temp`, `downloaded_files`, `staticfiles`, etc.
- pós-deploy: `pip install`, `migrate`, `collectstatic`, `reload apache2`

### Validar

1. Actions → “Deploy Melhor Preço DF” → Run workflow
2. No servidor: `ls -la /var/www/html/melhorprecodf.com.br` e logs do Actions sem erro

---

## Fase 2 — Apache + Django + SSL

### Vhost

```bash
cd /var/www/html/melhorprecodf.com.br
sudo a2enmod wsgi ssl rewrite headers
sudo cp deploy/apache-melhorprecodf.conf.example \
  /etc/apache2/sites-available/melhorprecodf.com.br.conf

# Se ainda não há certificado, deixe só o :80 ativo primeiro,
# ou rode certbot e deixe-o ajustar o SSL.
sudo a2ensite melhorprecodf.com.br
sudo apache2ctl configtest
sudo systemctl reload apache2
```

### Certbot

```bash
sudo certbot --apache -d melhorprecodf.com.br
# opcional: -d www.melhorprecodf.com.br
```

Se usar `www`, adicione em `ALLOWED_HOSTS` em `core/settings.py`.

### mod_wsgi × Python 3.12

```bash
# Qual Python o mod_wsgi do sistema usa?
python3 -c "import sys; print(sys.version)"
apache2ctl -M | grep wsgi
```

Se `libapache2-mod-wsgi-py3` não for 3.12, instale `mod_wsgi` no venv e aponte `LoadModule` no Apache para o `.so` do venv (documentação oficial mod_wsgi + virtualenv).

### Smoke test

```bash
cd /var/www/html/melhorprecodf.com.br
sudo -u www-data ./venv_3_12/bin/python manage.py check
curl -I https://melhorprecodf.com.br/
curl -I https://melhorprecodf.com.br/admin/
# Static: CSS/JS em /static/ sem 404
```

Logs: `/var/log/apache2/melhorprecodf-*-error.log`

---

## Fase 3 — Worker systemd + Xvfb

O worker roda `manage.py process_imports` a cada minuto como `www-data`, com `DISPLAY=:99`.

```bash
cd /var/www/html/melhorprecodf.com.br

sudo cp deploy/xvfb.service.example /etc/systemd/system/xvfb.service
sudo cp deploy/melhorpreco-worker.service /etc/systemd/system/
sudo cp deploy/melhorpreco-worker.timer /etc/systemd/system/

sudo mkdir -p /var/log/melhorpreco
sudo chown www-data:www-data /var/log/melhorpreco

sudo systemctl daemon-reload
sudo systemctl enable --now xvfb.service
sudo systemctl enable --now melhorpreco-worker.timer

systemctl status xvfb.service
systemctl list-timers | grep melhorpreco
sudo -u www-data env DISPLAY=:99 HOME=/var/www/html/melhorprecodf.com.br/chrome_temp \
  ./venv_3_12/bin/python manage.py process_imports
tail -f /var/log/melhorpreco/worker.log
```

Jobs SEFAZ/Caixa falham até a Fase 4 — esperado.

### Cron de e-mail (opcional)

```bash
cd /var/www/html/melhorprecodf.com.br
sudo -u www-data ./venv_3_12/bin/python manage.py crontab add
sudo -u www-data ./venv_3_12/bin/python manage.py crontab show
```

---

## Fase 4 — VPN L2TP + Squid

Você precisa (fora do git): **gateway**, **PSK IPsec**, **usuário/senha L2TP**.

Nomes de conexão **obrigatórios** (hardcoded no código):

- IPsec: `l2tp-ipsec`
- xl2tpd LAC: `vpn-connection`
- Range IP cliente esperado: `10.9.0.10`–`10.9.0.20` (peer `10.9.0.10`)

### Arquivos

```bash
cd /var/www/html/melhorprecodf.com.br

# 1) IPsec
sudo cp deploy/ipsec.conf.example /etc/ipsec.conf
sudo nano /etc/ipsec.conf   # troque VPN_GATEWAY_IP_OR_HOST

echo '%any %any : PSK "COLE_O_PSK_AQUI"' | sudo tee /etc/ipsec.secrets
sudo chmod 600 /etc/ipsec.secrets

# 2) xl2tpd + PPP
sudo cp deploy/xl2tpd.conf.example /etc/xl2tpd/xl2tpd.conf
sudo nano /etc/xl2tpd/xl2tpd.conf   # mesmo gateway

sudo cp deploy/options.l2tpd.client.example /etc/ppp/options.l2tpd.client
sudo nano /etc/ppp/options.l2tpd.client   # name = usuário L2TP
sudo chmod 600 /etc/ppp/options.l2tpd.client

# chap-secrets (usuário * senha *):
echo 'L2TP_USER * "L2TP_PASSWORD" *' | sudo tee -a /etc/ppp/chap-secrets
sudo chmod 600 /etc/ppp/chap-secrets

# 3) Squid
sudo cp deploy/squid.conf.example /etc/squid/squid.conf
sudo systemctl enable --now strongswan-starter   # nome do unit pode variar
sudo systemctl enable --now xl2tpd
sudo systemctl enable --now squid

# 4) sudoers para www-data
sudo cp deploy/sudoers-melhorpreco.example /etc/sudoers.d/melhorpreco
sudo chmod 440 /etc/sudoers.d/melhorpreco
sudo visudo -cf /etc/sudoers.d/melhorpreco
```

Se o unit do strongSwan for outro (`strongswan`, `ipsec`, `swanctl`), ajuste `systemctl enable`.

### Teste

```bash
sudo bash /var/www/html/melhorprecodf.com.br/deploy/vpn-up.sh
# Deve mostrar ppp0 IP em 10.9.0.x e o IP público via proxy Squid

curl -4 --max-time 20 --proxy http://127.0.0.1:3128 ifconfig.me
echo

# Como o worker (Django):
cd /var/www/html/melhorprecodf.com.br
sudo -u www-data env DISPLAY=:99 HOME=/var/www/html/melhorprecodf.com.br/chrome_temp \
  ./venv_3_12/bin/python manage.py shell -c \
  'from notas.sefaz import _setup_ppp0_interface; print(_setup_ppp0_interface())'
```

Pós-reboot: `sudo bash deploy/vpn-up.sh` ou deixe o primeiro job SEFAZ chamar `_setup_ppp0_interface()`.

---

## Fase 5 — Chrome / Selenium (+ Warsaw/Caixa)

### Google Chrome

```bash
# Instalar Chrome estável (ajuste URL se o Google mudar o pacote)
wget -q -O /tmp/chrome.deb https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
sudo apt install -y /tmp/chrome.deb
google-chrome --version
```

O código usa `version_main=151` (`notas/sefaz.py`, `caixa.py`, `views.py`, `caixa_banking.py`).
Se a major instalada for outra, atualize o pin no código para bater.

### Policy de proxy (obrigatória com extensions / Caixa)

```bash
sudo mkdir -p /etc/opt/chrome/policies/managed
sudo cp /var/www/html/melhorprecodf.com.br/deploy/chrome-proxy-policy.json.example \
  /etc/opt/chrome/policies/managed/proxy.json
```

### Permissões

```bash
sudo chown -R www-data:www-data \
  /var/www/html/melhorprecodf.com.br/chrome_temp \
  /var/www/html/melhorprecodf.com.br/downloaded_files
```

### Teste SEFAZ

1. Confirme VPN + Squid (Fase 4).
2. Enfileire um import no admin ou rode `process_imports` com job pendente.
3. Acompanhe `/var/log/melhorpreco/worker.log` e screenshots em `downloaded_files/`.

### Warsaw / Internet Banking Caixa (depois do SEFAZ estável)

Paths usados pelo worker (`notas/caixa_banking.py`):

- HOME Chrome: `/var/www/html/melhorprecodf.com.br/chrome_temp`
- Profile IB: `.../chrome_temp/caixa-profile` (não use `.config/google-chrome`)
- Credenciais: `/etc/melhorpreco/caixa.json` (0600, owner `www-data`)

#### A) Instalar Warsaw (sessão gráfica / xrdp como `ubuntu`)

1. Suba a VPN antes de abrir o Chrome (`sudo bash deploy/vpn-up.sh`) — policy de proxy força Squid.
2. Baixe `GBPCEFwr64.deb` no Internet Banking ou use o instalador:
   - https://www.caixa.gov.br/Downloads/warsaw/install-warsaw.run
3. Instale:

```bash
sudo apt-get install -y libnss3-tools libcurl4t64
sudo dpkg -i ~/Downloads/GBPCEFwr64.deb || true
sudo apt-get install -f -y
sudo systemctl restart warsaw
ps -ef | grep -i warsaw | grep -v grep
ss -ltnp | grep 30900   # deve escutar em 127.0.0.1:30900
```

#### B) NSS DB no Ubuntu 24.04 (se a Caixa diz “módulo não localizado”)

O daemon pode estar up e mesmo assim o Chrome rejeitar `wss://127.0.0.1:30900` se
`~/.pki/nssdb` estiver vazio. Importe o cert do Warsaw (como **ubuntu**, sem sudo):

```bash
bash /var/www/html/melhorprecodf.com.br/deploy/ensure-warsaw-nssdb-ubuntu.sh
# ou manualmente: openssl s_client → certutil -A (ver script)
```

Confirme `ProxyBypassList` com `127.0.0.1,localhost` em
`/etc/opt/chrome/policies/managed/proxy.json`. Feche todo o Chrome e reabra o IB.
Cadastre o dispositivo; a autorização no ATM pode levar até 48h.

#### C) Handoff para o worker (pode adiantar antes do ATM)

Feche o Chrome do `ubuntu`, depois:

```bash
cd /var/www/html/melhorprecodf.com.br
sudo bash deploy/handoff-caixa-profile.sh
sudo nano /etc/melhorpreco/caixa.json   # se ainda for o example
# Remova _README; preencha username, senha_login (8), senha_assinatura (6)
sudo chown www-data:www-data /etc/melhorpreco/caixa.json
sudo chmod 600 /etc/melhorpreco/caixa.json
```

O script copia `~/.config/google-chrome` → `chrome_temp/caixa-profile`, roda
`sync-warsaw-nssdb.sh` e valida leitura por `www-data`.

Dry-run / apostas reais só **depois** da liberação no ATM.

---

## Referência rápida de paths

| Path | Uso |
|------|-----|
| `/var/www/html/melhorprecodf.com.br` | App + `venv_3_12` |
| `.../chrome_temp` | `HOME` do Chrome (`www-data`) |
| `.../downloaded_files` | Screenshots Selenium |
| `/var/log/melhorpreco/worker.log` | Log do timer |
| `/etc/melhorpreco/caixa.json` | Credenciais Caixa |
| `/etc/squid/squid.conf` | Proxy local `:3128` |
| `/etc/sudoers.d/melhorpreco` | VPN/Squid para `www-data` |

## Scripts e units no repo

| Arquivo | Função |
|---------|--------|
| `deploy/vpn-up.sh` | Sobe ppp0 + policy routing + Squid |
| `deploy/sync-warsaw-nssdb.sh` | Copia NSS DB Warsaw → `chrome_temp` |
| `deploy/ensure-warsaw-nssdb-ubuntu.sh` | Cria NSS DB do ubuntu a partir do cert :30900 |
| `deploy/handoff-caixa-profile.sh` | Copia profile Chrome + NSS + prepara caixa.json |
| `deploy/melhorpreco-worker.service` / `.timer` | Fila DF a cada minuto (`:00`) |
| `deploy/melhorpreco-ro-worker.service` / `.timer` | Fila RO a cada minuto (`:30`), mesmo ppp0/Squid |
| `deploy/*.example` | Templates Apache, VPN, Squid, Xvfb, sudoers |

## Troubleshooting

| Sintoma | Checar |
|---------|--------|
| Actions falha no rsync | Secrets, `authorized_keys`, porta SSH, firewall |
| Apache 500 | `melhorprecodf-*-error.log`, MySQL, `python-home` do WSGI |
| Worker não roda | `systemctl status xvfb`, `list-timers`, permissões do log |
| `ppp0` não sobe | `ipsec status`, logs xl2tpd, PSK/gateway, `chap-secrets` |
| Squid sem IP BR | `tcp_outgoing_address`, `ip rule`, `vpn-up.sh` |
| Chrome “wrong version” | `google-chrome --version` vs `version_main=` |
| Caixa pede Warsaw | daemon `:30900`, NSS DB `~/.pki/nssdb`, `ensure-warsaw-nssdb-ubuntu.sh`, bypass proxy localhost |
| Worker sem Warsaw | `handoff-caixa-profile.sh`, `sync-warsaw-nssdb.sh`, permissões `caixa-profile` |

---

## Rondônia (`melhorprecoro.com.br`)

Mesmo repositório e o **mesmo ppp0 + Squid :3128** do DF. O que muda:

- Checkout em `/var/www/html/melhorprecoro.com.br` (venv, `chrome_temp` e `downloaded_files` próprios)
- `SITE_UF=RO`, prefixo de chave `11`, banco/usuário `melhorprecoro`
- `/etc/melhorprecoro/django.env` (veja `deploy/django.env.ro.example`)
- Vhost Apache `melhorprecoro.com.br` com `WSGIDaemonProcess` próprio
- Worker `melhorpreco-ro-worker.service` + timer no segundo `:30` (o DF continua no `:00`)

Os dois workers usam o mesmo `/tmp/import_by_key.lock` — só um Chrome/VPN por vez. Mega-Sena/Caixa ficam desligados em RO.

```bash
sudo mkdir -p /var/www/html/melhorprecoro.com.br /var/log/melhorpreco
sudo chown ubuntu:www-data /var/www/html/melhorprecoro.com.br
sudo chmod 775 /var/www/html/melhorprecoro.com.br

# clone ou rsync do mesmo repo
cd /var/www/html/melhorprecoro.com.br
python3.12 -m venv venv_3_12
./venv_3_12/bin/pip install -r requirements.txt
mkdir -p chrome_temp downloaded_files staticfiles
sudo chown -R ubuntu:www-data .
sudo chown -R www-data:www-data chrome_temp downloaded_files
sudo chmod 775 chrome_temp downloaded_files

sudo mkdir -p /etc/melhorprecoro
sudo cp deploy/django.env.ro.example /etc/melhorprecoro/django.env
sudo nano /etc/melhorprecoro/django.env   # senha do MySQL
sudo chown ubuntu:www-data /etc/melhorprecoro/django.env
sudo chmod 640 /etc/melhorprecoro/django.env

SITE_UF=RO DJANGO_ENV_FILE=/etc/melhorprecoro/django.env \
  ./venv_3_12/bin/python manage.py migrate --noinput
SITE_UF=RO DJANGO_ENV_FILE=/etc/melhorprecoro/django.env \
  ./venv_3_12/bin/python manage.py collectstatic --noinput

sudo cp deploy/apache-melhorprecoro.conf.example \
  /etc/apache2/sites-available/melhorprecoro.com.br.conf
sudo cp deploy/apache-melhorprecoro-le-ssl.conf.example \
  /etc/apache2/sites-available/melhorprecoro.com.br-le-ssl.conf
sudo a2ensite melhorprecoro.com.br melhorprecoro.com.br-le-ssl
sudo certbot --apache -d melhorprecoro.com.br

sudo touch /var/log/melhorpreco/worker-ro.log
sudo chown www-data:www-data /var/log/melhorpreco/worker-ro.log
sudo cp deploy/melhorpreco-ro-worker.service /etc/systemd/system/
sudo cp deploy/melhorpreco-ro-worker.timer /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable --now melhorpreco-ro-worker.timer
```

DNS `melhorprecoro.com.br` e o banco `melhorprecoro` precisam existir antes. O sudoers de `www-data` (VPN/Squid) é o mesmo do DF.
