Disaster Recovery e Continuidade#
Plano de recuperação de desastres e continuidade de negócio para o site UNICEF Portugal.
1. Identificação de Riscos#
| Risco | Probabilidade | Impacto | Mitigação |
|---|---|---|---|
| App Service crash/hang | Alta (atual) | Alto | Always On + Auto Heal + Health Check |
| SQL Database corrupção | Baixa | Crítico | Backups automáticos Azure (PITR) |
| SQL DTU throttling | Média | Alto | Monitorização + escalamento |
| Storage account indisponível | Muito baixa | Alto | Redundância LRS |
| Front Door/CDN falha | Muito baixa | Alto | Failover automático Azure |
| Perda de código fonte | Muito baixa | Crítico | Azure DevOps + GitHub mirror |
| Credential leak | Baixa | Crítico | Key Vault + rotação |
2. Backup e Restauro#
Azure SQL (PITR - Point In Time Restore)#
O Azure SQL Standard tier oferece 14 dias de retenção de backups automáticos. É possível restaurar a base de dados para qualquer ponto nos últimos 14 dias.
# Restaurar para um ponto no tempo
az sql db restore \
--dest-name uncdb-prd-restored \
--edition Standard \
--service-objective S1 \
--time "2026-04-13T12:00:00Z" \
--resource-group unc-prd \
--server uncsqlsrv-prd \
--name uncdb-prd \
--subscription 2e6c7ed6-c6f8-4058-901c-c3113a4df82a
Nota
Após o restore, a nova base de dados terá o nome uncdb-prd-restored. Será necessário atualizar a connection string do App Service para apontar para a nova BD, ou renomear as bases de dados.
Blob Storage#
| Propriedade | Valor |
|---|---|
| Storage account | uncstorageprd |
| Redundância | LRS (Locally Redundant Storage) |
| Conteúdo | Media e imagens do Umbraco |
Para backup manual do blob storage:
az storage blob download-batch \
--destination ./backup \
--source <container> \
--account-name uncstorageprd \
--subscription 2e6c7ed6-c6f8-4058-901c-c3113a4df82a
Recomendação
Ativar soft delete e versioning no blob storage para proteção adicional contra eliminação acidental.
Código fonte#
| Localização | URL |
|---|---|
| Azure DevOps (principal) | https://dev.azure.com/double-pt/Unicef/_git/Unicef |
| GitHub (mirror) | https://github.com/BetacodeTech/UNC.PublicPortal.git |
Importante
Garantir que ambos os repositórios estão sincronizados. Verificar periodicamente que o mirror no GitHub está atualizado.
3. Procedimento de Recuperação Total#
flowchart TD
A[Incidente detetado] --> B{Identificar o problema}
B -->|App Service| C[Restart do App Service]
B -->|Base de dados| D[Verificar SQL Server]
B -->|Storage| E[Verificar Blob Storage]
B -->|DNS/Rede| F[Verificar Azure DNS]
C --> C1{Resolveu?}
C1 -->|Sim| Z[Monitorizar e documentar]
C1 -->|Nao| C2[Redeploy do staging slot]
C2 --> C3{Resolveu?}
C3 -->|Sim| Z
C3 -->|Nao| C4[Escalar App Service Plan]
C4 --> C5{Resolveu?}
C5 -->|Sim| Z
C5 -->|Nao| X[Escalar para equipa dev]
D --> D1{SQL acessivel?}
D1 -->|Nao| D2[Verificar firewall e estado do servidor]
D1 -->|Sim mas lento| D3[DTU throttling?]
D3 -->|Sim| D4[Escalar tier SQL temporariamente]
D1 -->|Dados corrompidos| D5[PITR Restore]
D5 --> D6[Criar BD restaurada]
D6 --> D7[Atualizar connection string]
D7 --> D8[Restart App Service]
D8 --> Z
D4 --> Z
D2 --> Z
E --> E1{Container acessivel?}
E1 -->|Nao| E2[Verificar estado do storage account]
E1 -->|Ficheiros em falta| E3[Restaurar de backup]
E2 --> Z
E3 --> Z
F --> F1[Verificar registos DNS Azure]
F1 --> F2{DNS correto?}
F2 -->|Nao| F3[Corrigir registos DNS]
F2 -->|Sim| F4[Verificar Front Door / CDN]
F3 --> Z
F4 --> Z
X --> Z
Passo a passo detalhado#
Se o problema é o App Service#
- Restart: Ver Runbook de Restart
- Redeploy: Swap com staging slot
- Escalar: Aumentar tier do App Service Plan temporariamente
Se o problema é a base de dados#
-
Verificar acesso:
az sql db show \ --name uncdb-prd \ --server uncsqlsrv-prd \ --resource-group unc-prd \ --subscription 2e6c7ed6-c6f8-4058-901c-c3113a4df82a -
PITR Restore (se necessário):
az sql db restore \ --dest-name uncdb-prd-restored \ --edition Standard \ --service-objective S1 \ --time "2026-04-13T12:00:00Z" \ --resource-group unc-prd \ --server uncsqlsrv-prd \ --name uncdb-prd \ --subscription 2e6c7ed6-c6f8-4058-901c-c3113a4df82a -
Atualizar connection string do App Service:
az webapp config connection-string set \ --name uncwebprd \ --resource-group unc-prd \ --connection-string-type SQLAzure \ --settings umbracoDbDSN="Server=tcp:uncsqlsrv-prd.database.windows.net,1433;Database=uncdb-prd-restored;..." \ --subscription 2e6c7ed6-c6f8-4058-901c-c3113a4df82a
Se o problema é o storage#
-
Verificar estado:
az storage account show \ --name uncstorageprd \ --resource-group unc-prd \ --subscription 2e6c7ed6-c6f8-4058-901c-c3113a4df82a -
Listar containers:
az storage container list \ --account-name uncstorageprd \ --subscription 2e6c7ed6-c6f8-4058-901c-c3113a4df82a
Se o problema é DNS#
- Verificar registos DNS no Azure Portal
- Confirmar que o domínio
www.unicef.ptaponta para o App Service correto - Verificar certificado SSL
4. Monitorização Proativa (A IMPLEMENTAR)#
As seguintes medidas de monitorização devem ser implementadas para detetar problemas antes que afetem os utilizadores.
Application Insights#
Ativar Application Insights no App Service para recolha de telemetria:
- Tempo de resposta dos pedidos
- Taxa de erros
- Exceções do servidor
- Utilização de memória e CPU
Availability Tests (Testes de Disponibilidade)#
Configurar testes automáticos de disponibilidade:
Teste 1 - Homepage Ping:
- URL:
https://www.unicef.pt - Frequência: A cada 5 minutos
- Localizações: 5 regiões diferentes
- Timeout: 120 segundos
az monitor app-insights web-test create \
--web-test-name "Homepage-Ping" \
--resource-group unc-prd \
--location northeurope \
--defined-web-test-name "Homepage Ping Test" \
--web-test-kind "ping" \
--subscription 2e6c7ed6-c6f8-4058-901c-c3113a4df82a \
--urls "https://www.unicef.pt" \
--frequency 300 \
--timeout 120 \
--enabled true
Teste 2 - API Ping:
- URL:
https://www.unicef.pt/umbraco/Api/ContentApi/GetData/?url=/ - Frequência: A cada 5 minutos
- Validação: Resposta HTTP 200 com conteúdo JSON
az monitor app-insights web-test create \
--web-test-name "API-Ping" \
--resource-group unc-prd \
--location northeurope \
--defined-web-test-name "API Ping Test" \
--web-test-kind "ping" \
--subscription 2e6c7ed6-c6f8-4058-901c-c3113a4df82a \
--urls "https://www.unicef.pt/umbraco/Api/ContentApi/GetData/?url=/" \
--frequency 300 \
--timeout 120 \
--enabled true
Alert Rules (Regras de Alerta)#
Configurar os seguintes alertas:
| Métrica | Condição | Ação |
|---|---|---|
| Response time | > 10s durante 5 minutos | Email equipa |
| Failed requests | > 10% durante 5 minutos | Email equipa |
| Server exceptions | > 0 | Email equipa |
| Memory | > 80% | Email equipa |
| Health Check failures | Consecutivas | Auto restart (via Auto Heal) |
Monitorização externa#
Recomenda-se complementar a monitorização Azure com um serviço externo independente como backup:
- Serviços recomendados: UptimeRobot, Better Stack ou Checkly
- Endpoints a monitorizar:
https://www.unicef.pt— homepage carregahttps://www.unicef.pt/umbraco/Api/ContentApi/GetData/?url=/— API responde com JSON
- Alertas: Via Slack ou email se indisponível por mais de 2 minutos
- Vantagem: Funciona mesmo que toda a infraestrutura Azure tenha problemas
5. RPO e RTO#
| Métrica | Valor | Notas |
|---|---|---|
| RPO (Recovery Point Objective) | ~5 minutos | Azure SQL PITR com backups contínuos |
| RTO - App crash | ~3-5 minutos | Restart simples do App Service |
| RTO - DB restore | ~30-60 minutos | PITR restore + atualização de connection string |
| RTO - Full redeploy | ~1-2 horas | Rebuild + deploy + configuração |
O que significa#
- RPO de 5 minutos: Em caso de perda de dados, perdem-se no máximo os últimos 5 minutos de alterações na base de dados
- RTO de 3-5 minutos: Para o cenário mais comum (app crash), o site pode ser restaurado em 3-5 minutos com um restart
- RTO de 1-2 horas: No pior cenário (perda total), o site pode ser reconstruído em 1-2 horas a partir do código fonte e backups
Checklist de verificação periódica#
Executar mensalmente:
- [ ] Verificar que o mirror GitHub está sincronizado com Azure DevOps
- [ ] Confirmar que os backups SQL estão ativos (14 dias de retenção)
- [ ] Testar que o staging slot tem uma versão funcional
- [ ] Verificar que o soft delete está ativo no blob storage
- [ ] Rever os alertas configurados e confirmar que os emails estão atualizados
- [ ] Testar o procedimento de restart documentado