Post de Teste — Todos os Elementos
Parágrafo introdutório com negrito, itálico, e código inline. Este post existe para
testar todos os elementos visuais do tema.
Tipografia
Heading nível 3
Heading nível 4
Heading nível 5
Heading nível 6
Parágrafo longo para avaliar legibilidade real do corpo do texto. Administrar um homelab é mais do que apenas manter servidores funcionando — é um laboratório contínuo de aprendizado. Cada serviço que você sobe, cada pipeline de CI que você configura, cada container que você orquestra adiciona uma camada de experiência prática que nenhum curso consegue replicar completamente. A combinação de Proxmox, ZFS, Traefik e um cluster Kubernetes local cria um ambiente que espelha o que você encontra em produção, mas com a liberdade de quebrar coisas e aprender com os erros sem consequências reais.
Parágrafo com negrito, itálico, tachado, código inline, negrito com código e
uma combinação de itálico com link externo dentro do mesmo parágrafo.
Também testando uso de Ctrl+Alt+Del para teclas de teclado.
Blockquote simples: configure, quebre, aprenda, repare. Essa é a filosofia do homelab.
Blockquote com múltiplas linhas e formatação negrita e
código inlinedentro da citação. Isso testa se o estilo do blockquote se mantém consistente com elementos aninhados.Blockquote aninhado — citação dentro de citação. Testa o recuo e a borda visual do tema.
Código
Bash / Shell
# Instalar Proxmox VE
apt update && apt full-upgrade -y
wget https://enterprise.proxmox.com/debian/proxmox-release-bookworm.gpg
dpkg -i proxmox-release-bookworm.gpg
apt update && apt install proxmox-ve -y
# Loop com condição
for node in pve01 pve02 pve03; do
ssh root@${node} "pvecm status && uptime"
done
YAML
services:
traefik:
image: traefik:v3.0
restart: unless-stopped
ports:
- "80:80"
- "443:443"
environment:
- CF_DNS_API_TOKEN=${CLOUDFLARE_TOKEN}
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ./certs:/certs
labels:
- "traefik.enable=true"
Python
import subprocess
import json
from pathlib import Path
def get_vm_list(node: str) -> list[dict]:
"""Retorna lista de VMs de um nó Proxmox via SSH."""
result = subprocess.run(
["ssh", f"root@{node}", "pvesh get /nodes/{node}/qemu --output-format json"],
capture_output=True, text=True
)
if result.returncode != 0:
raise RuntimeError(f"Falha ao conectar em {node}: {result.stderr}")
return json.loads(result.stdout)
vms = get_vm_list("pve01")
for vm in vms:
print(f" [{vm['vmid']}] {vm['name']} — {vm['status']}")
JavaScript / TypeScript
// Busca posts via API e renderiza cards
async function fetchPosts(tag = null) {
const url = tag ? `/api/posts?tag=${tag}` : '/api/posts';
const response = await fetch(url);
if (!response.ok) throw new Error(`HTTP ${response.status}`);
const posts = await response.json();
return posts
.filter(p => p.published)
.sort((a, b) => new Date(b.date) - new Date(a.date));
}
const container = document.querySelector('#posts');
fetchPosts('homelab').then(posts => {
container.innerHTML = posts
.map(p => `<article><h2>${p.title}</h2><p>${p.excerpt}</p></article>`)
.join('');
});
Nginx
server {
listen 443 ssl http2;
server_name raphazilla.rocks;
ssl_certificate /etc/letsencrypt/live/raphazilla.rocks/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/raphazilla.rocks/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_cache_bypass $http_upgrade;
}
location ~* \.(css|js|png|ico)$ {
expires 30d;
add_header Cache-Control "public, immutable";
}
}
Dockerfile
FROM debian:bookworm-slim AS builder
ARG MARMITE_VERSION=0.2.6
WORKDIR /build
RUN apt-get update && apt-get install -y --no-install-recommends \
curl ca-certificates && rm -rf /var/lib/apt/lists/*
RUN curl -fsSL \
"https://github.com/rochacbruno/marmite/releases/download/v${MARMITE_VERSION}/marmite-x86_64-unknown-linux-musl.tar.gz" \
| tar -xz -C /usr/local/bin
FROM debian:bookworm-slim
COPY --from=builder /usr/local/bin/marmite /usr/local/bin/marmite
WORKDIR /content
ENTRYPOINT ["/usr/local/bin/marmite"]
CMD [". /site --serve"]
Terraform / HCL
resource "proxmox_vm_qemu" "homelab_node" {
count = 3
name = "k8s-node-${count.index + 1}"
target_node = "pve01"
clone = "debian-12-cloud"
cores = 4
memory = 8192
disk {
storage = "local-zfs"
size = "50G"
type = "scsi"
}
network {
bridge = "vmbr0"
model = "virtio"
}
ipconfig0 = "ip=192.168.10.${count.index + 11}/24,gw=192.168.10.1"
}
Ansible (YAML)
---
- name: Configurar servidores Proxmox
hosts: proxmox_nodes
become: true
vars:
packages:
- htop
- iotop
- net-tools
- tmux
tasks:
- name: Atualizar cache apt
ansible.builtin.apt:
update_cache: true
cache_valid_time: 3600
- name: Instalar pacotes essenciais
ansible.builtin.apt:
name: "{{ packages }}"
state: present
- name: Habilitar e iniciar serviço SSH
ansible.builtin.systemd:
name: ssh
enabled: true
state: started
JSON
{
"homelab": {
"nodes": [
{
"name": "pve01",
"ip": "192.168.10.1",
"role": "master",
"specs": { "cpu": 16, "ram_gb": 64, "storage_tb": 4 }
},
{
"name": "pve02",
"ip": "192.168.10.2",
"role": "worker",
"specs": { "cpu": 8, "ram_gb": 32, "storage_tb": 2 }
}
],
"network": {
"vlan_mgmt": 10,
"vlan_vms": 20,
"vlan_storage": 30
}
}
}
SQL
-- Relatório de uso por serviço
SELECT
s.name AS service,
s.type,
ROUND(s.ram_mb / 1024.0, 1) AS ram_gb,
s.cpu_cores,
COUNT(r.id) AS restarts_30d,
MAX(r.restarted_at) AS last_restart
FROM services s
LEFT JOIN restart_log r
ON r.service_id = s.id
AND r.restarted_at >= NOW() - INTERVAL '30 days'
WHERE s.active = true
GROUP BY s.id, s.name, s.type, s.ram_mb, s.cpu_cores
ORDER BY ram_gb DESC;
Rust
use std::collections::HashMap;
use std::time::{Duration, Instant};
struct Cache<T> {
store: HashMap<String, (T, Instant)>,
ttl: Duration,
}
impl<T: Clone> Cache<T> {
fn new(ttl_secs: u64) -> Self {
Self {
store: HashMap::new(),
ttl: Duration::from_secs(ttl_secs),
}
}
fn get(&self, key: &str) -> Option<&T> {
self.store.get(key).and_then(|(val, ts)| {
if ts.elapsed() < self.ttl { Some(val) } else { None }
})
}
fn set(&mut self, key: String, value: T) {
self.store.insert(key, (value, Instant::now()));
}
}
Listas
Não-ordenada simples
- Proxmox VE como hypervisor principal
- KVM para VMs de produção
- LXC para containers leves
- ZFS como sistema de arquivos
Ordenada simples
- Instalar o sistema base
- Configurar a rede
- Adicionar storage
- Criar as primeiras VMs
Lista aninhada
- Hypervisors
- Proxmox VE
- KVM para VMs pesadas
- LXC para containers leves
- ESXi (apenas teste)
- Proxmox VE
- Storage
- ZFS com RAID-Z2
- NFS para backups
- Rede
- Switch gerenciável principal
- VLANs por segmento
- Firewall OPNsense
Task list (checklist)
- Instalar Proxmox VE
- Configurar ZFS pool
- Subir Traefik como reverse proxy
- Configurar DNS interno com AdGuard
- Migrar VMs para cluster de 3 nós
- Implementar monitoramento com Grafana
- Automatizar backups com Restic
Lista com código inline e formatação
- Use
pvecm statuspara verificar o status do cluster - O arquivo de configuração fica em
/etc/pve/corosync.conf - Nunca remova um nó do cluster sem antes fazer
pvecm delnode
Tabelas
Tabela simples
| Serviço | Tipo | RAM | CPU |
|---|---|---|---|
| Proxmox | VM | 8 GB | 4 |
| Traefik | LXC | 512MB | 1 |
| Gitea | LXC | 1 GB | 2 |
| Jellyfin | VM | 4 GB | 4 |
Tabela com alinhamento e código nas células
| Comando | Descrição | Tempo médio |
|---|---|---|
apt update |
Atualiza o índice de pacotes | ~2 s |
pvecm status |
Status do cluster Proxmox | <1 s |
zpool scrub tank |
Verifica integridade do ZFS pool | 4–8 h |
restic backup /etc |
Backup incremental com Restic | 10–60s |
Elementos HTML
Teclas de teclado
Para reiniciar o servidor: Ctrl+Alt+Del
Para salvar no vim: pressione Esc, depois :wq
Details / Summary (accordion)
Ver configuração completa do Traefik
O arquivo traefik.yml principal deve ficar em /etc/traefik/traefik.yml.
Configurações dinâmicas vão em /etc/traefik/conf.d/*.yml.
api:
dashboard: true
insecure: false
entryPoints:
web:
address: ":80"
http:
redirections:
entrypoint:
to: websecure
websecure:
address: ":443"
certificatesResolvers:
letsencrypt:
acme:
email: admin@raphazilla.rocks
storage: /certs/acme.json
dnsChallenge:
provider: cloudflare
Comandos úteis para diagnóstico de rede
ss -tulnp— portas abertas e processos associadosip route show— tabela de roteamentotcpdump -i eth0 port 443— captura de pacotes na porta 443nft list ruleset— regras de firewall (nftables)
Callouts
corosync para comunicação entre nós do cluster.
Certifique-se de que a porta 5405/udp esteja liberada no firewall interno.
pct exec <id> -- bash para abrir um shell diretamente em um container LXC
sem precisar de SSH configurado dentro dele.
zpool destroy apaga todos os dados do pool permanentemente.
Sempre confirme o nome do pool antes de executar o comando.
pvecm delnode <nome> com o nó desligado.
Links
- Documentação do Proxmox
- Marmite SSG
- Post relacionado: My First Post with Marmite and Ansible