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 inline dentro 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

  1. Instalar o sistema base
  2. Configurar a rede
  3. Adicionar storage
  4. Criar as primeiras VMs

Lista aninhada

  • Hypervisors
    • Proxmox VE
      • KVM para VMs pesadas
      • LXC para containers leves
    • ESXi (apenas teste)
  • Storage
    • ZFS com RAID-Z2
    • NFS para backups
  • Rede
    1. Switch gerenciável principal
    2. VLANs por segmento
    3. 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 status para 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 associados
  • ip route show — tabela de roteamento
  • tcpdump -i eth0 port 443 — captura de pacotes na porta 443
  • nft list ruleset — regras de firewall (nftables)

Callouts

Info O Proxmox VE usa corosync para comunicação entre nós do cluster. Certifique-se de que a porta 5405/udp esteja liberada no firewall interno.
📝
Nota O ZFS não precisa de RAID de hardware — ele gerencia redundância por software. Misturar discos de tamanhos diferentes em um pool pode reduzir a capacidade total utilizável.
💡
Dica Use pct exec <id> -- bash para abrir um shell diretamente em um container LXC sem precisar de SSH configurado dentro dele.
Atenção Executar zpool destroy apaga todos os dados do pool permanentemente. Sempre confirme o nome do pool antes de executar o comando.
🚨
Perigo Nunca remova um nó do cluster Proxmox enquanto ele estiver online. Isso pode corromper o quorum e derrubar todos os serviços em execução no cluster. Faça sempre via pvecm delnode <nome> com o nó desligado.

Links