Jan. 26, 2026, 11:12 p.m.
Este Website
Áudios
*Conteúdo gerado por IA
Arquitetura Técnica: caiodonalisio.com
Este documento descreve a arquitetura técnica do site caiodonalisio.com, abordando desde a infraestrutura de rede até o pipeline de CI/CD.
Visão Geral
Internet
↓
Cloudflare Tunnel
↓
NGINX → static files
↓
Django/Gunicorn
↓
PostgreSQL ←→ Redis
1. Infraestrutura de Rede
Hardware
O site roda em um single-node Kubernetes cluster hospedado em um mini-PC local. A topologia de rede é a seguinte:
Internet
↓
Mikrotik Router (RouterOS)
• Inter-VLAN routing
• Firewall per VLAN
↓ trunk port (tagged)
Managed Switch (VLAN-aware)
• VLAN 10: Doméstica
• VLAN 20: Servidores
• VLAN 30: IoT
↓ access port (VLAN 20)
Mini-PC
• Ubuntu Server
• K3s single-node
Isolamento via VLAN
O servidor reside em uma VLAN dedicada (VLAN 20), isolada do restante da rede doméstica. O Mikrotik gerencia:
- Firewall inter-VLAN: a VLAN de servidores não tem acesso à rede doméstica
- Acesso de gerenciamento: apenas dispositivos específicos da VLAN Principal podem acessar SSH
- Saída para internet: permitida para o Cloudflare Tunnel estabelecer conexão outbound
Essa segmentação garante que mesmo em caso de comprometimento do servidor, o atacante não teria acesso lateral aos dispositivos domésticos.
Exposição à Internet
Não há port forwarding no roteador. Todo o tráfego de entrada passa pelo Cloudflare Tunnel, que mantém uma conexão outbound persistente com a edge da Cloudflare. Isso elimina a necessidade de:
- IP público estático
- Portas abertas no firewall
- Gerenciamento manual de certificados TLS
2. Kubernetes (K3s)
Cluster
K3s single-node com os seguintes recursos deployados no namespace caiodonalisio:
| Recurso | Réplicas | Função | |---------|----------|--------| | Django/Gunicorn | 2 | Aplicação web | | NGINX | 1 | Reverse proxy + static files | | PostgreSQL | 1 | Banco de dados | | Redis | 1 | Cache + session store | | Cloudflared | 1 | Tunnel daemon |
Storage
Utiliza local-path provisioner do K3s:
- staticfiles-pvc (2Gi): arquivos estáticos coletados
- media-pvc (2Gi): uploads e arquivos de mídia
- postgres-pvc (10Gi): dados do PostgreSQL
Health Checks e Resiliência
O deployment do Django configura:
```yaml readinessProbe: httpGet: path: /health/ port: 3334 initialDelaySeconds: 60 periodSeconds: 15 failureThreshold: 3
livenessProbe: httpGet: path: /health/ port: 3334 initialDelaySeconds: 90 periodSeconds: 30 failureThreshold: 5 ```
Combinado com PodDisruptionBudget (minAvailable: 1) e rolling updates (maxUnavailable: 0, maxSurge: 1), garante zero-downtime durante deploys.
Graceful Shutdown
Pre-stop hook com sleep de 15 segundos permite que conexões em andamento sejam drenadas antes do SIGTERM:
yaml
lifecycle:
preStop:
exec:
command: ["/bin/sh", "-c", "sleep 15"]
3. Cloudflare Tunnel
O daemon cloudflared roda como deployment no cluster, configurado via ConfigMap:
yaml
tunnel: <tunnel-id>
credentials-file: /etc/cloudflared/creds/credentials.json
ingress:
- hostname: caiodonalisio.com
service: http://nginx-svc:80
- hostname: www.caiodonalisio.com
service: http://nginx-svc:80
- service: http_status:404
Configurações relevantes:
- hostNetwork: true: evita problemas de 502 intermitente em clusters single-node
- dnsPolicy: ClusterFirstWithHostNet: mantém resolução de serviços internos
- protocol: http2: conexão multiplexada com a edge
4. Stack da Aplicação
Backend
| Componente | Versão | Configuração | |------------|--------|--------------| | Python | 3.12 | - | | Django | 5.1 | Settings modulares (dev/prod/test) | | Gunicorn | - | 4 workers, port 3334 | | Celery | 5.4 | Configurado, workers desabilitados |
Banco de Dados e Cache
| Componente | Versão | Uso | |------------|--------|-----| | PostgreSQL | 16.4 | Persistência principal | | Redis | 7.4.1 | Sessions, cache, Celery broker |
Estrutura Django
``` website/ # Configurações do projeto ├── settings/ │ ├── base.py │ ├── production.py │ └── development.py ├── urls.py # Rotas + endpoint /health/ └── celery.py
blog/ # App principal ├── models.py # Post, PostFile, PostBook ├── views.py # Renderização Markdown └── storage.py # OverwriteStorage customizado
accounts/ # Autenticação └── models.py # CustomUser
pages/ # Páginas estáticas ```
Serving
- NGINX: reverse proxy, serve
/static/e/media/diretamente - WhiteNoise: fallback para static files com CompressedManifestStaticFilesStorage
- Gunicorn: WSGI server para requisições dinâmicas
5. CI/CD Pipeline
GitHub Actions
O workflow build_release.yml executa em push para main:
Test (pytest)
↓
Build (docker)
↓
Semantic Release
↓
├→ Trivy Scan
├→ Push to Docker Hub
└→ Update K8s Manifests
↓
Argo CD Auto-Sync
Semantic Versioning
Versões geradas automaticamente via python-semantic-release:
fix:→ PATCHfeat:→ MINORBREAKING CHANGE:→ MAJOR
GitOps com Argo CD
Argo CD monitora o diretório k8s/ e aplica mudanças automaticamente:
yaml
syncPolicy:
automated:
prune: true
selfHeal: true
retry:
limit: 5
backoff:
duration: 5s
maxDuration: 3m
factor: 2
O job update-k8s-manifest do GitHub Actions atualiza a tag da imagem em k8s/website.yml, triggering o sync do Argo CD.
6. Containerização
Multi-stage Build
```dockerfile
Stage 1: Builder
FROM python:3.12.4-slim AS builder COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/ RUN uv pip compile requirements.txt -o requirements.lock RUN uv pip sync requirements.lock
Stage 2: Runtime
FROM python:3.12.4-slim COPY --from=builder /.venv /.venv COPY . /usr/src/ EXPOSE 3334 CMD ["./entrypoint.sh"] ```
O uso de uv (package manager em Rust) acelera significativamente o build de dependências.
Entrypoint
O entrypoint.sh executa na inicialização do container:
- Aguarda PostgreSQL (healthcheck via netcat)
collectstaticmigrate- Sync de arquivos de mídia
- Inicia Gunicorn
7. Fluxo Completo de uma Requisição
INTERNET
↓
CLOUDFLARE EDGE
(DDoS, SSL)
↓ tunnel
MIKROTIK → VLAN 20 → Mini-PC
↓
K3s CLUSTER
↓
cloudflared (hostNetwork)
↓
nginx-svc
• /static/ → staticfiles-pvc
• /media/ → media-pvc
• /* → website-svc
↓
website-svc (2 replicas)
Django + Gunicorn :3334
↓
postgres-svc ←→ redis-svc
8. Considerações de Segurança
| Camada | Medida | |--------|--------| | Rede | Isolamento via VLAN, sem port forwarding | | Edge | Cloudflare DDoS protection, WAF | | Transporte | TLS gerenciado pela Cloudflare | | Cluster | Network policies, secrets para credenciais | | Aplicação | CSRF, secure cookies, ALLOWED_HOSTS | | CI/CD | Trivy scan para vulnerabilidades em imagens |
Última atualização: Janeiro de 2026
Estrutura do Projeto
Abaixo está a árvore de diretórios completa do repositório, gerada automaticamente.
Escrevi este breve texto para registrar a motivação e as experiências que tive por trás da montagem deste website. Espero que seja de interesse daqueles que queiram saber como foi o processo de aprendizado e construção ou planejem fazer algo parecido.
Motivação
Como analista de dados, tenho bastante familiaridade com tarefas como coletar dados da internet, realizar regressões, inferências ou programar processamentos de dados com machine learning utilizando R e Python (com uma pitada de C++). Todas essas atividades podem ser feitas localmente no meu próprio computador, com frequência completamente offline.
Sem dúvida são habilidades importantes de se possuir para o que eu gosto de fazer. No entanto, o mundo está mudando e a tendência crescente, já há algum tempo, é a de se exportar qualquer atividade computacional para a nuvem, isto é, um computador não-local, ao qual temos acesso apenas remotamente. Junto com o mundo, precisamos nós também mudarmos!
Se por um lado estudo ativamente sobre algoritmos, estatística e processamento de dados, ainda restava uma bastante incômoda lacuna no meu conhecimento: como integrar o poder da internet tanto para processar dados quanto para exportar e publicar os meus resultados? Como realizar e publicar inferências e visualização de dados automaticamente sem precisar deixar meu computador pessoal ligado? Estas foram as questões que me motivaram a aprender a lidar com a web.
A maneira mais óbvia de começar a fazer isso é aprender a montar um website, ponderei. Somado ao aprendizado, eu poderia assim ter uma plataforma como trampolim para explorar novas tecnologias, para exposição de projetos e, no espírito open-source da internet e do mundo da programação, compartilhamento dos meus estudos pessoais, sejam em programação, sejam em economia, sejam em história, meus objetos de maior interesse (com a vantagem ainda de me incentivar a realizar uma leitura mais ativa dos livros e artigos que eu escolho ler). Seria possível de fazer isso utilizando simplesmente o Blogspot, um conhecido portal de blogs, ou o GitHub, a principal plataforma de compartilhamento de códigos e projetos, mas eu gostaria de me comunicar também com pessoas de fora do mundo da programação e de uma maneira mais personalizada.
Escolhas
Resta então a questão: como montar um website? Tentando resolver este problema, logo descobri o interessante e diverso mundo do web-development e rapidamente aprendi como, utilizando serviços de servidores compartilhados e designs já prontos livremente disponíveis, é simples e barato criar uma página acessível a qualquer um no mundo. Em 5 minutos um usuário com pouquíssima experiência é capaz de fazê-lo a partir do zero. A primeira versão deste meu website pessoal, do fim de 2020, foi feita desta forma. No entanto, não existe qualquer desafio nisso e páginas com estas ferramentas têm flexibilidade limitada, o que me motivou a ir além.
Muito resumidamente, um site tem três partes: o back-end, que lida com a lógica e realiza as operação e o processamento de dados de um website, o front-end, responsável pelos elementos fazem a intermediação entre o usuário e o back-end, e o servidor, que armazena e disponibiliza os arquivos para qualquer um com acesso à internet visualizar.
Na linguagem Python, em que geralmente programo, há uma série de bibliotecas extremamente úteis para análise de dados, logo aprendi a lidar com Numpy, Pandas, SciKitLearn e tantas outras essenciais, mas ainda restava uma para mim desconhecida: Django.
Django é uma das grandes e celebradas ferramentas do Python, usada como framework para criar aplicações na web, uma ótima opção para construir o back-end. É bastante robusta e sofisticada, estando presente em produtos como Spotify e Instagram. Ainda que não seja o único pacote com esse fim, me pareceu a escolha natural para que eu pudesse aumentar meu repertório em Python, aprender na prática os fundamentos de web-development e ter um site pessoal.
Este é um site simples e de baixo tráfego, então não haveria necessidade de utilizar uma ferramenta tão poderosa, mas não resisti à oportunidade de aprender este framework tão importante e popular, além de tornar a interação com o banco de dados bastante simples.
Quanto ao front-end, considerei utilizar os bastante apreciados React.js ou Vue.js, que podem ser adaptados para uso com Django. Boa parte da comunidade faz isso, mas como prefiro focar no estudo de ferramentas propriamente de análise de dados, não encontrei boa justificativa para optar por algo além de Django-templates, que já faz parte do framework selecionado, somado de CSS com Bootstrap, que são simples, eficazes e perfeitamente à altura do que eu desejava criar.
.accordion-body, though the transition does limit overflow.
.accordion-body, though the transition does limit overflow.
Por fim, permanece apenas a seleção do servidor. Se por um lado todos as outras decisões eram tomadas com critérios técnicos, aqui entra mais uma variável: o custo.
Os enormes e pesados servidores no canto do escritório sempre me causaram uma forte impressão, mas como não tenho dados e processamentos muito volumosos ou confidenciais nem preciso de um novo aquecedor para a minha casa, não haveria por que ter um servidor físico, mesmo um pequeno. A escolha por um servidor na nuvem é muito mais barata, conveniente e óbvia.
No entanto, a nuvem não é uma, mas muitas. O mercado de computação em nuvem cresce rapidamente, e com ele, o número de companhias que oferecem este tipo de serviço. A Google e a Microsoft têm apresentado algumas inovações neste segmento e seus market-shares vêm subindo - A Microsoft Azure é bastante apreciada nas comunidades de machine-learning.
No entanto, a principal plataforma de nuvem utilizada no mundo é a AWS, da Amazon, e me pareceu vantajoso escolhê-la para posteriormente integrar e aprender outros dos incontáveis serviços que a AWS oferece, como o AWS-Lambda e o Sagemaker. Não menos importante é o fato de na minha pesquisa a AWS ter o preço mais competitivo e previsível – o custo costuma ser calculado conforme o uso – do que seus concorrentes, posso dormir com a tranquilidade de não ter que me preocupar com uma fatura surpresa de US$ 90.
Com todas as engrenagens devidamente selecionadas, eu tinha um plano! Basta apenas tirá-lo do papel.
Execução
Meu primeiro obstáculo foi descobrir que o mundo web é movido a Linux, um sistema operacional open-source bastante distinto do Windows. Se eu quisesse configurar um servidor para o meu website, eu precisaria reaprender a interagir com as funções mais básicas do computador.
Para a minha sorte, no ano de 2021 isso é mais fácil do que nunca! Se até poucos tempo atrás eu teria que instalar uma máquina virtual ou acomodar um segundo sistema operacional junto ao Windows, o que é bastante trabalhoso, hoje ter um computador com Linux é tão simples quanto instalar o Whatsapp. Avanço tecnológico não significa apenas criar coisas novas, mas também facilitar as antigas.
Após brincar e seguir vários guias por muitas horas neste playground local e sem compromissos, eu já me sentia preparado para lidar com o meu servidor na nuvem de verdade.
Antes de fazer isso, no entanto, mais importante ainda era criar o projeto Django em si, o website, no meu próprio computador para depois colocá-lo no servidor. Felizmente esta é uma ferramenta com uma excelente documentação e com muito material para aprender como lidar. embora não seja das coisas mais simples que existem em Python, logo me acostumei a lidar com os templates, views, models e os outros elementos para fazer tudo funcionar conforme o planejado.
Quanto ao design em si, recorri a um dos muitos modelos livremente disponíveis na internet, que modifiquei completamente para acomodar aos meus gostos. Com uma breve introdução e incontáveis tentativas e erros para lidar com a linguagem HTML e CSS (essa é a parte mais trabalhosa e que requer mais ajustes finos), auxiliado pelos elementos prontos do Bootstrap, consegui enfim criar uma webpage com todas as partes necessárias.
Com um site que funcionasse perfeitamente na minha máquina, em uma agradável manhã de sábado consegui aprender a lidar com os básicos de desempenho e segurança do software do servidor, o Nginx, que julguei mais adequado e robusto do que o também popular Apache.
O último passo afinal foi agregar tudo isso. Seguindo rigorosamente guias para fazer isso, instalei o servidor NginX no servidor Linux contratado na nuvem, o qual serve à internet o meu projeto Django (conectado e acoplado a um banco de dados PostgreSQL), utilizando como intermediador o software Gunicorn, e é por meio destas tecnologias que eu disponibilizo este conteúdo.
Sem dúvida realizar todas essas operações agregou muitos conhecimentos ao meu repertório e já me sinto bastante mais confortável lidando com servidores, APIs e a internet em geral. Com um site bem-estruturado, funcional, bonito e agradável de navegar (espero que concorde!), já tenho toda estrutura necessária para adicionar com facilidade mais dos meus projetos, textos e cadernos futuros exatamente da forma como eu projetei e focar nos meus interesses de análise de dados e afins.