Infraestrutura
O WordPress de cursos roda no cluster Kubernetes da Oracle Cloud (OKE), no namespace
legacy-sites, dividindo os nós com a produção do FUJI. Foi migrado em setembro/2026 do
docker-compose da VM Azure. Desde 02/10/2026 é gerenciado por GitOps (pasta legacy-sites/
do repositório gitops, aplicada pelo ArgoCD).
Visão geral
| Item | Valor |
|---|---|
Cluster |
OKE |
Nós |
2 × |
Namespace |
|
Entrada |
|
Certificado de origem |
cert-manager, |
DNS / CDN |
Cloudflare, zona |
Gestão |
GitOps: pasta |
Recursos Kubernetes
| Recurso | Nome | Detalhes |
|---|---|---|
Deployment |
|
1 réplica, estratégia * |
Service |
|
ClusterIP, porta 80 → 8080 (nginx do pod) |
StatefulSet |
|
1 réplica, imagem |
Service |
|
ClusterIP, porta 3306 ( |
PersistentVolumeClaim |
|
50Gi, |
PersistentVolumeClaim |
|
50Gi, |
Ingress |
|
Classe |
Secret (TLS) |
|
Let’s Encrypt, cobre |
ConfigMap |
|
Server block do nginx do pod. Inclui o bloqueio do XML-RPC
( |
ConfigMap |
|
Montado em |
Secret |
|
Senha do |
Secret |
|
|
| Os Secrets são criados manualmente (o SOPS está desativado no projeto). As senhas do MariaDB foram trocadas em 02/10/2026 e só existem nos Secrets; não há cópia em repositório. |
Outros recursos do namespace, fora do escopo deste módulo: static-root (página estática do
apex) e wp-fuji (desligado, 0 réplicas, com seu próprio PVC wp-content-fuji).
DNS e Cloudflare
A zona artesmarciaisonline.com.br fica numa conta Cloudflare e é editada à mão no painel. Ela
não está no Terraform do iac; trazê-la para lá é uma pendência registrada.
| Registro | Tipo | Conteúdo | Proxy |
|---|---|---|---|
|
A |
|
ligado |
|
A |
|
ligado |
|
CNAME |
|
ligado |
|
A |
|
desligado — remover |
Com o proxy ligado, existem dois certificados: o da borda (emitido pela
Cloudflare e apresentado ao visitante) e o de origem (Let’s Encrypt, emitido pelo cert-manager
no cluster). Desligar o proxy faz o visitante ver diretamente o certificado de origem; o
cert-manager precisa de acesso HTTP direto ao /.well-known/acme-challenge/ para renovar.
|
Regras e recomendações do painel da zona:
-
regra de WAF (custom rule, ação Block) com a expressão
starts_with(http.request.uri.path, "/xmlrpc.php"), ativa desde 02/10/2026 (ver Bloqueio do XML-RPC em duas camadas); -
não ligar o Bot Fight Mode sem antes confirmar que nenhum retorno automático de pagamento (WooCommerce / Paid Memberships Pro) ou o ManageWP depende de acesso automatizado.
Bloqueio do XML-RPC em duas camadas
O XML-RPC foi o canal do spam e da força bruta no incidente (ver Incidente: invasão do WordPress de cursos (ago–out/2026)). Ele é bloqueado na borda e na origem:
| Camada | Regra | Efeito |
|---|---|---|
Cloudflare (WAF) |
|
A requisição nem chega ao cluster; o visitante vê a página de bloqueio da Cloudflare (403). |
nginx do pod |
|
Segunda camada, caso o proxy seja desligado ou a regra do WAF removida. |
A primeira versão do bloqueio (location = /xmlrpc.php no nginx e
uri.path eq "/xmlrpc.php" no WAF) só casava o caminho exato. Com o cgi.fix_pathinfo padrão
do PHP-FPM, POST /xmlrpc.php/xmlrpc.php executava o xmlrpc.php normalmente, e a força bruta
seguiu por esse caminho até a correção, em 02/10/2026. O teste correto é funcional: um
POST com o método inofensivo demo.sayHello não pode responder Hello! em nenhuma variação
de caminho. A checagem periódica (/wp-invasao, no repositório iac) faz esse teste.
|
/XMLRPC.php (maiúsculas) passa pelo WAF, que diferencia maiúsculas, mas recebe 404 na
origem, porque o arquivo não existe com esse nome.
GitOps
Tudo o que é Kubernetes está versionado em gitops/legacy-sites/ (Kustomize): Deployments,
StatefulSet, Services, PVCs, Ingress e as configurações do nginx e do PHP-FPM, guardadas como
arquivos .conf em config/. Uma mudança é um commit na main; o ArgoCD sincroniza sozinho.
Antes do commit, conferir:
kustomize build legacy-sites | kubectl --context oracle -n legacy-sites diff -f -
| Ponto | Detalhe |
|---|---|
Fora do Git |
Os Secrets ( |
PVCs |
Anotados com |
Sem |
Uma mudança feita com |
ConfigMaps |
Mudar só a configuração não reinicia o pod. O nginx precisa de reload
( |
Sandbox (homologação)
Cópia do site para ensaiar atualizações sem tocar na produção, em legacy-sites-staging
(gitops/legacy-sites-staging/, Application legacy-sites-staging). É um overlay de
legacy-sites: mesmas imagens e configurações, só com wp-cursos e mariadb; o que difere
está declarado no overlay.
| Item | Detalhe |
|---|---|
Acesso |
IP público próprio, |
Proteção |
TLS no nginx do pod com uma cópia do certificado da produção; senha (basic auth, Secret
|
Isolamento |
Mu-plugin Cuidado ao clonar: o |
Dados |
Cópia fiel da produção (dados pessoais reais; acesso sob confidencialidade), feita pelo
|
Versões em teste |
Bloco |
Custo |
NLB sem custo; ~0,2 vCPU e ~0,9 GiB de requests nos nós compartilhados com o FUJI.
Desligar com |
Operação do dia a dia
# estado dos pods
kubectl --context oracle -n legacy-sites get pods
# logs de acesso (nginx) e do PHP-FPM
kubectl --context oracle -n legacy-sites logs deploy/wp-cursos -c nginx --since=10m
kubectl --context oracle -n legacy-sites logs deploy/wp-cursos -c wordpress --since=10m
# console SQL (a senha vem do ambiente do próprio pod; aspas simples são obrigatórias)
kubectl --context oracle -n legacy-sites exec -it mariadb-0 -- \
sh -c 'mysql -uroot -p"$MYSQL_ROOT_PASSWORD" enj'
# reiniciar o WordPress (estratégia Recreate: há alguns segundos de indisponibilidade)
kubectl --context oracle -n legacy-sites rollout restart deployment/wp-cursos
# tirar o site do ar rapidamente (ex.: nova suspeita de invasão); registrar replicas: 0 no gitops depois
kubectl --context oracle -n legacy-sites scale deployment/wp-cursos --replicas=0
Não existe phpMyAdmin no cluster, de propósito. Para acesso gráfico ao banco, use
kubectl port-forward svc/mariadb 3306 e um cliente local, só durante o uso.
|
Lacunas conhecidas
| Lacuna | Situação |
|---|---|
Backup |
Backup lógico diário (para um bucket OCI) e snapshot dos discos implementados em 03/10/2026,
ver Backup e restore. A lacuna só fecha depois da ativação e do primeiro backup
conferido. O plugin UpdraftPlus está instalado, mas a configuração não foi verificada. Antes
disso, o último backup conhecido é o dump de 02/10/2026 (anterior à limpeza), guardado no disco
da VM Azure ( |
Isolamento de rede |
O cluster usa Flannel sem controller de |
Isolamento de nós |
Roda nos mesmos nós da produção do FUJI. Um pico de CPU aqui afeta o FUJI. |
Monitoramento |
A verificação externa ( |
Desempenho de disco |
Os PVCs usam o tier padrão do |
Software |
WordPress 4.9.9, PHP 7.2, MariaDB 10.3 e tema pirateado, todos sem suporte. Ver Guia de atualização. |
Ambiente anterior (VM Azure)
Até 02/10/2026 o site rodava num docker-compose (/opt/docker) na VM Azure
fujivm.brazilsouth.cloudapp.azure.com (20.195.168.150), junto com o PostgreSQL do FUJI.
Os containers foram parados em 02/10/2026 com restart=no, e os volumes foram preservados
como evidência do incidente. Ainda em 02/10/2026 a VM aparecia como desalocada (VM
deallocated). O disco continua existindo e guarda os logs do nginx, o dump de 02/10 e os
volumes originais; eles devem ser copiados antes de a VM ser destruída junto com o restante da
Azure (item 6.6 da migração).