# Publicação e manutenção (Ubuntu + Nginx + PHP-FPM + MySQL)

Guia para publicar https://drilharob.ao num servidor Ubuntu 24.04 LTS. Os ficheiros de exemplo estão em `docs/deploy/`.

## 1. Pacotes do servidor

```bash
sudo apt update && sudo apt install -y nginx mysql-server supervisor git unzip certbot python3-certbot-nginx \
  php8.3-fpm php8.3-cli php8.3-mysql php8.3-gd php8.3-intl php8.3-mbstring php8.3-xml php8.3-zip php8.3-curl php8.3-bcmath
curl -sS https://getcomposer.org/installer | php && sudo mv composer.phar /usr/local/bin/composer
curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash - && sudo apt install -y nodejs
```

Em `/etc/php/8.3/fpm/php.ini`: `upload_max_filesize = 64M`, `post_max_size = 64M`, `memory_limit = 512M`, `expose_php = Off`.

## 2. Base de dados

```sql
CREATE DATABASE drilharob CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'drilharob'@'localhost' IDENTIFIED BY 'palavra-passe-forte';
GRANT ALL PRIVILEGES ON drilharob.* TO 'drilharob'@'localhost';
```

## 3. Aplicação

```bash
sudo mkdir -p /var/www/drilharob && sudo chown $USER:www-data /var/www/drilharob
git clone <repositório> /var/www/drilharob/current && cd /var/www/drilharob/current
cp .env.example .env    # preencher DB_*, MAIL_*, ADMIN_EMAIL, ADMIN_PASSWORD
composer install --no-dev --optimize-autoloader
npm ci && npm run build # gera public/build e bootstrap/ssr
php artisan key:generate
php artisan migrate --seed --force
php artisan storage:link
php artisan optimize
sudo chown -R www-data:www-data storage bootstrap/cache
sudo chmod -R ug+rwX storage bootstrap/cache
```

Crie a conta master (fora do `.env`; a palavra-passe é pedida interactivamente):

```bash
php artisan app:master --email=info@itcore.ao
```

Depois do primeiro acesso, **remova `ADMIN_PASSWORD` do `.env`** e altere a palavra-passe do Administrador no portal.

> Apache com mod_php: se aparecer «Allocation of JIT memory failed», confirme que `public/.htaccess` (que define `pcre.jit 0`) é lido (`AllowOverride All`) ou defina `pcre.jit=0` no `php.ini` do Apache.

## 4. Domínios, Nginx e SSL

O portal administrativo responde só em **https://admin.drilharob.ao** (`ADMIN_DOMAIN` no `.env`). Em https://drilharob.ao/admin, e em qualquer caminho `/admin/...` do site público, a resposta é **404 Página não encontrada**, para qualquer método HTTP. O subdomínio de administração não serve páginas públicas.

1. DNS: registos `A` (e `AAAA`, se aplicável) para `drilharob.ao`, `www.drilharob.ao` e `admin.drilharob.ao`, a apontar para o servidor.
2. `.env`: `APP_URL=https://drilharob.ao` e `ADMIN_DOMAIN=admin.drilharob.ao`.
3. A sessão do portal fica no subdomínio (não defina `SESSION_DOMAIN`), por isso os cookies de administração nunca são enviados ao site público.

```bash
sudo cp docs/deploy/nginx.conf /etc/nginx/sites-available/drilharob.ao
sudo ln -s /etc/nginx/sites-available/drilharob.ao /etc/nginx/sites-enabled/
sudo certbot --nginx -d drilharob.ao -d www.drilharob.ao -d admin.drilharob.ao
sudo nginx -t && sudo systemctl reload nginx
```

O Certbot instala a renovação automática do certificado. Com Apache, use `docs/deploy/apache-production.conf` e `certbot --apache` com os mesmos três domínios.

Verificação após publicar:

```bash
curl -I https://drilharob.ao/admin            # 404
curl -I https://admin.drilharob.ao/           # 302 → /admin → /admin/login
```

## 5. Filas, SSR e tarefas agendadas

```bash
sudo cp docs/deploy/supervisor.conf /etc/supervisor/conf.d/drilharob.conf
sudo supervisorctl reread && sudo supervisorctl update
( crontab -l -u www-data 2>/dev/null; echo "* * * * * cd /var/www/drilharob/current && php artisan schedule:run >> /dev/null 2>&1" ) | sudo crontab -u www-data -
```

- **Fila** (`queue:work`): variantes de imagem e emails de notificação.
- **SSR** (`inertia:start-ssr`): renderização no servidor para motores de pesquisa e partilhas. Se parar, o site continua a funcionar (os metadados SEO são sempre gerados pelo Laravel).
- **Agendador** (`routes/console.php`): publicação de artigos agendados (cada minuto), backup diário da BD às 02:30, backup semanal com ficheiros, limpeza de logs.

## 6. Email

Configure `MAIL_*` com um servidor SMTP (ex.: o do domínio drilharob.ao). Teste com:

```bash
php artisan tinker --execute="Mail::raw('Teste', fn(\$m) => \$m->to('geral@drilharob.ao')->subject('Teste'));"
```

Os destinatários das notificações de orçamentos e mensagens são definidos no portal em **Configurações → Notificações**.

## 7. Backups

- Automáticos: `storage/app/private/backups/` (BD diária, retenção 14 dias; BD + ficheiros semanal, retenção 30 dias).
- Manual: `php artisan backup:run` ou `php artisan backup:run --with-media`.
- **Copie regularmente esta pasta para fora do servidor** (ex.: `rclone` para armazenamento externo).
- Restauro: `gunzip < db_AAAA-MM-DD.sql.gz | mysql -u drilharob -p drilharob` e, para ficheiros, `tar -xzf media_….tar.gz -C storage/app`.

## 8. Actualizações

```bash
cd /var/www/drilharob/current && ./docs/deploy/deploy.sh
```

O script coloca o site em manutenção, actualiza dependências, compila o frontend, aplica migrations, regista novas permissões, refresca caches e reinicia filas e SSR.

## 9. Segurança — checklist

- `APP_ENV=production`, `APP_DEBUG=false`, `SESSION_SECURE_COOKIE=true`, `SESSION_ENCRYPT=true`.
- 2FA obrigatório em produção (activado pelo seeder; ver **Configurações → Integrações e segurança**).
- Anexos dos pedidos de orçamento ficam em `storage/app/private` e só são servidos a utilizadores autorizados.
- Firewall: `sudo ufw allow OpenSSH && sudo ufw allow 'Nginx Full' && sudo ufw enable`.
- Actualizações do sistema: `sudo apt install unattended-upgrades`.
- Logs: `storage/logs/laravel-*.log`; auditoria de acções no portal em **Registos de actividade**.

## 10. Problemas frequentes

| Sintoma | Causa provável |
|---|---|
| Imagens sem versão WebP | Worker da fila parado: `sudo supervisorctl status` |
| Emails não chegam | `MAIL_*` incorrectos ou fila parada; ver `storage/logs` |
| Artigos agendados não publicam | Cron do agendador em falta |
| Alterações de configuração não aparecem | `php artisan optimize:clear` após editar o `.env` |
| Erro 419 ao enviar formulários | Sessão expirada ou `APP_URL`/`SESSION_DOMAIN` incorrectos |
