⚡ AutomationsAI|Portal de Cursos →

Verificando acesso...

TRILHA 2

🐳 Postiz Self-Hosted

Suba sua própria instância do Postiz com Docker Compose: agendador open-source de posts para X, Bluesky, LinkedIn, Mastodon e mais. Do VPS ao primeiro post programado via API.

5
Módulos
30
Tópicos
~4h
Duração
Intermediário
Nível

Mapa da trilha

Conteúdo detalhado

2.1 ~30 min

📋 Pré-requisitos

Tudo que você precisa ter pronto antes de tocar no docker-compose: máquina, rede, email e armazenamento.

O que é:

Servidor virtual Linux (Ubuntu 22.04+) com pelo menos 2 GB de RAM e 1 vCPU. Postiz + Postgres + Redis cabem confortavelmente em CX22 da Hetzner (~€4) ou Droplet básico ($6) da DigitalOcean.

Por que aprender:

Self-hosted exige máquina sempre ligada com IP público. Escolher mal o tamanho gera OOM kill do Postgres; escolher caro demais é desperdício para uso pessoal/pequena equipe.

Conceitos-chave:

2 GB RAM mínimo, 20 GB SSD, IPv4 público, snapshots semanais, firewall (UFW) liberando 22/80/443.

O que é:

Docker Engine roda os containers; Docker Compose v2 (integrado como plugin) orquestra múltiplos serviços via docker-compose.yml. Instalação oficial: curl -fsSL https://get.docker.com | sh.

Por que aprender:

Postiz oficialmente recomenda compose como deploy padrão. Sem isso, você teria que rodar Postgres, Redis, frontend e workers separadamente — dor de cabeça desnecessária.

Conceitos-chave:

docker --version ≥ 24, plugin compose v2 (docker compose sem hífen), usuário no grupo docker, restart policies.

O que é:

Subdomínio apontando (registro A) para o IP do seu VPS. Necessário para HTTPS via Let's Encrypt e para OAuth funcionar (X e LinkedIn exigem callback HTTPS).

Por que aprender:

Sem domínio, callbacks OAuth quebram, cookies de sessão falham em produção e você fica preso a HTTP em IP cru — inseguro e impossível de usar com X/LinkedIn.

Conceitos-chave:

Registro A, TTL baixo durante setup, Cloudflare proxy desligado para gerar cert, propagação DNS (5-30 min).

O que é:

Provedor SMTP/API para Postiz mandar email de boas-vindas, reset de senha e convites de membros. Resend é grátis até 3.000 emails/mês e tem API key simples.

Por que aprender:

Sem email configurado você não consegue convidar ninguém pra organização nem recuperar senha — efeitos só aparecem quando você precisa.

Conceitos-chave:

SMTP host, porta 587 (STARTTLS), API key Resend, registros SPF/DKIM no DNS, FROM_EMAIL_ADDRESS no .env.

O que é:

Bucket S3-compatible para armazenar imagens e vídeos dos posts. R2 da Cloudflare não cobra egress; MinIO roda no próprio compose e fica em /var/lib/minio.

Por que aprender:

Postiz precisa servir mídia via URL pública para X/Bluesky baixarem. Salvar local no container quebra em reinicializações e estoura disco rápido.

Conceitos-chave:

Access key, secret key, endpoint URL, bucket público, CORS liberando o domínio do Postiz.

O que é:

Conforto para abrir SSH, editar arquivos (.env, docker-compose.yml), ler logs (docker compose logs -f) e reiniciar serviços (docker compose restart postiz).

Por que aprender:

Self-hosted = você é o sysadmin. Quando algo quebra (e vai quebrar uma vez), saber ler log e editar variável é a diferença entre 10 min e 3h.

Conceitos-chave:

SSH com chave (não senha), tail -f, grep ERROR, screen/tmux para sessões longas.

Ver Completo
2.2 ~50 min

🚀 Setup com Docker Compose

Do git clone ao docker compose up -d: o módulo exemplar com cada arquivo dissecado.

O que é:

Arquivo YAML que declara 3 serviços: postiz (app), postgres e redis. Imagem oficial em ghcr.io/gitroomhq/postiz-app:latest, porta 5000 exposta internamente e mapeada para 5000 do host (ou via reverse proxy).

Por que aprender:

Saber editar esse arquivo é o que separa "instalei o Postiz" de "rodo Postiz em produção". Healthchecks, volumes nomeados e depends_on evitam corrida de start-up.

Conceitos-chave:

services, volumes nomeados (postgres-data), depends_on com condition: service_healthy, restart: unless-stopped, env_file: .env.

O que é:

Arquivo .env com segredos e configuração: JWT_SECRET (gerar com openssl rand -hex 32), MAIN_URL=https://postiz.seudominio.com, DATABASE_URL=postgresql://postiz:senha@postgres:5432/postiz, REDIS_URL=redis://redis:6379, credenciais S3 e SMTP.

Por que aprender:

90% dos erros de "Postiz não sobe" são variável faltando ou URL errada (http vs https, localhost vs nome do service). Dominar o .env é dominar 80% do troubleshooting.

Conceitos-chave:

.env nunca no git (use .env.example), nome do service Docker é o hostname dentro da rede, NEXT_PUBLIC_* vai pro browser, secrets em 32+ caracteres.

O que é:

Postgres 14+ guarda contas conectadas, posts agendados e organizações. Redis (7+) faz filas BullMQ dos jobs de publicação e cache de sessão. Ambos como containers irmãos do Postiz com volumes nomeados.

Por que aprender:

Sem volume nomeado, você perde TODOS os posts agendados no primeiro docker compose down -v. Sem Redis, jobs de publicação não rodam — posts ficam "scheduled" para sempre.

Conceitos-chave:

Volumes postgres-data:/var/lib/postgresql/data, healthcheck pg_isready, Redis sem persistência (efêmero ok), backup diário do volume.

O que é:

Comando docker compose up -d em modo detached. Na primeira execução baixa imagens (~1.5 GB), cria volumes, sobe Postgres, roda migrations Prisma automaticamente e inicia o frontend na porta 5000.

Por que aprender:

Saber a sequência esperada (pull → create volume → start postgres → wait healthy → migrate → start postiz) ajuda a identificar onde travou se algo der errado.

Conceitos-chave:

Flag -d (detached), --build para imagem custom, --force-recreate após editar .env, primeira subida demora 3-5 min.

O que é:

Comandos docker compose logs -f postiz (follow), --tail 200 para últimas linhas, docker compose ps para estado e docker stats para uso de CPU/RAM por container.

Por que aprender:

Erros comuns na primeira subida: ECONNREFUSED (Redis ainda subindo), migration falhou (DB credentials), porta 5000 já em uso. Todos visíveis no log.

Conceitos-chave:

Filtrar por service, separar stdout/stderr, exportar log com > postiz.log, log rotation no daemon.json.

O que é:

Três checks: (a) docker compose ps mostra 3 serviços Up (healthy); (b) curl http://localhost:5000 devolve HTML do Next.js; (c) abrir https://postiz.seudominio.com mostra tela de login.

Por que aprender:

"Está rodando" é diferente de "está funcionando". Validar saúde antes de chamar a tropa garante que você não vai descobrir erro só quando o primeiro usuário tentar logar.

Conceitos-chave:

Endpoint /api/health, status code 200, conexão DB OK no log, screenshot da tela de signup salvo.

Ver Completo
2.3 ~35 min

🔧 Primeiro acesso e configuração

Container subiu — agora é hora de criar usuário, configurar storage na UI e montar a primeira organização.

O que é:

Postiz não tem "admin global" — o primeiro signup vira automaticamente owner da primeira organização criada. Abra /auth/register, preencha email, senha e confirme via email (se SMTP estiver configurado).

Por que aprender:

Quem cria primeiro tem o controle. Em deploy interno, registre você antes de divulgar a URL para a equipe, ou alguém vira owner por engano.

Conceitos-chave:

DISABLE_REGISTRATION=true após primeiro user, role owner ≠ admin, recuperação de senha via email transacional.

O que é:

3 áreas principais: Launches (calendário visual e agendamento), Analytics (métricas por rede e por post), Settings (organização, integrações, billing). Sidebar à esquerda navega entre elas.

Por que aprender:

Conhecer o mapa da UI poupa minutos por dia. Calendário arrastável é o ponto forte do Postiz e está no Launches.

Conceitos-chave:

Drag-and-drop no calendário, modal de "novo post" multi-rede, dark mode nativo, switch entre organizações no topo.

O que é:

Em Settings → Storage Provider, escolha entre local (não recomendado) ou cloudflare. Cole endpoint R2, access key, secret key, bucket name e a URL pública. Teste upload de imagem.

Por que aprender:

Storage mal configurado = posts com imagem ficam sem mídia. X retorna 400 silenciosamente quando URL da imagem é privada.

Conceitos-chave:

CLOUDFLARE_ACCOUNT_ID, CLOUDFLARE_ACCESS_KEY, CLOUDFLARE_BUCKETNAME, CLOUDFLARE_BUCKET_URL, CORS allow-origin.

O que é:

No .env: EMAIL_PROVIDER=resend + RESEND_API_KEY=re_xxx + EMAIL_FROM_NAME=Postiz + EMAIL_FROM_ADDRESS=noreply@seudominio.com. Reinicie e teste mandando convite para si mesmo.

Por que aprender:

Sem email, "convidar membro" só gera link manual. SPF/DKIM faltando = email vai pra spam ou nem entrega.

Conceitos-chave:

Resend domain verification, SPF TXT record, DKIM CNAME, FROM com domínio próprio (não @gmail).

O que é:

Organization é o "workspace" do Postiz: agrupa contas de redes sociais, membros e posts. Você pode ter várias (ex: "Pessoal" e "ClienteX"). Criada automaticamente no primeiro signup; novas em Settings → Organizations.

Por que aprender:

Separação por organização é o que permite gerenciar múltiplos clientes/projetos sem misturar contas conectadas e analytics.

Conceitos-chave:

Org = boundary de billing, role no nível da org, switch via dropdown, slug único.

O que é:

Em Settings → Team Members, click "Invite", informe email e role. Postiz envia email com link de aceite que cria a conta vinculada à org. Roles: admin (tudo menos billing), user (cria/edita posts), viewer (só lê).

Por que aprender:

Compartilhar credencial é antipattern. Cada pessoa com login próprio gera histórico auditável de quem publicou o quê.

Conceitos-chave:

Convite expira em 7 dias, role editável depois, remover membro não apaga posts dele, audit log por usuário.

Ver Completo
2.4 ~40 min

🔌 Conectando contas

A parte que importa: plugar X, Bluesky, LinkedIn e Mastodon — e ver o primeiro post sair pra cada rede.

O que é:

Bluesky usa ATProto, não OAuth. Em Launches → "+", escolha Bluesky, informe handle (ex: você.bsky.social) e um app password criado em bsky.app/settings/app-passwords. Conexão é instantânea, sem callback.

Por que aprender:

É a conta mais fácil de plugar — bom primeiro teste end-to-end. Se Bluesky funciona, o pipeline (DB → fila → publisher) está ok.

Conceitos-chave:

App password ≠ senha principal, revogável independentemente, sem rate limit agressivo, 300 chars por post.

O que é:

Crie app no developer.x.com, copie Client ID/Secret para X_API_KEY e X_API_SECRET no .env, configure callback https://postiz.seudominio.com/integrations/social/x. No Postiz, click "Connect X" e autorize.

Por que aprender:

X é a rede mais quebradiça: callback URL exata, scopes específicos (tweet.write, users.read), API v2 paga limita free tier.

Conceitos-chave:

OAuth 2.0 com PKCE, refresh token rotativo, free tier = 1.500 posts/mês, callback case-sensitive.

O que é:

Crie app em linkedin.com/developers, peça produtos "Share on LinkedIn" e "Sign In with LinkedIn using OpenID Connect". Configure LINKEDIN_CLIENT_ID / LINKEDIN_CLIENT_SECRET no .env. No Postiz, escolha entre conta pessoal e Company Page (admin obrigatório).

Por que aprender:

LinkedIn é a rede com maior fricção: aprovação manual de "Share on LinkedIn" pode demorar dias. Iniciar cedo no curso.

Conceitos-chave:

Scope w_member_social, w_organization_social para páginas, token expira em 60 dias.

O que é:

Mastodon é federado: cada instância (ex: mastodon.social, tech.lgbt) tem OAuth próprio. No Postiz, informe a URL da sua instância, ele cria app via API, redireciona e finaliza. Sem developer portal centralizado.

Por que aprender:

É a única rede onde você não depende de aprovação da big tech. Ótimo para teste sem risco e para audiência tech.

Conceitos-chave:

Endpoint /api/v1/apps registra app dinamicamente, scopes read write, 500 chars padrão (varia por instância).

O que é:

No calendário Launches, click em um horário futuro, selecione TODAS as contas conectadas, escreva o post, opcionalmente customize por rede (botão "Customize per channel"), confirme. Postiz cria N jobs Redis (um por rede) com publish_at futuro.

Por que aprender:

Este é o "Hello World" do Postiz. Funcionou em 4 redes simultâneas = self-host está validado.

Conceitos-chave:

Per-channel content (X tem 280, LinkedIn 3000), upload de mídia uma vez, timezone do user, retry automático em falha temporária.

O que é:

Aba Analytics agrega métricas que cada rede expõe via API: impressões (X, LinkedIn), reposts (Bluesky), favorites (Mastodon). Atualização ~6h após publicar. Filtros por rede, por período e por post.

Por que aprender:

Sem dados, "agendar" é só automação cega. Cruzar horário × engajamento revela quando vale postar.

Conceitos-chave:

Métricas variam por rede (LinkedIn não dá impressão fora de Pages), cache de 6h, export CSV, comparação org-wide.

Ver Completo
2.5 ~35 min

🔗 API e webhooks

Postar pela UI é manual. A API REST do Postiz transforma sua instância em um endpoint pra qualquer app que você quiser.

O que é:

Postiz expõe rotas /public/v1/* protegidas por API key. Habilitar via API_LIMIT=30 (req/min) e DISABLE_PUBLIC_API=false no .env. Reinicie o container após.

Por que aprender:

Sem API, Postiz é só dashboard. Com API, vira backend headless de publicação para seus apps.

Conceitos-chave:

Rate limit por API key, escopo por org, Swagger disponível em /docs, versionamento via prefix.

O que é:

Em Settings → API, click "Generate new key", dê um label (ex: "n8n-prod") e copie o token mostrado UMA vez (formato pk_live_...). Postiz armazena hash, não o token cru — perdeu = gera outro.

Por que aprender:

Uma chave por integração permite revogar uma sem afetar as outras quando algo vazar.

Conceitos-chave:

Token visible only once, vinculado à org, sem expiração default, last_used_at para auditoria.

O que é:

Comando: curl -X POST https://postiz.seudominio.com/public/v1/posts -H "Authorization: pk_live_xxx" -H "Content-Type: application/json" -d '{"type":"schedule","date":"2026-06-01T15:00:00Z","posts":[{"integration":{"id":"INT_ID"},"value":[{"content":"Hello from API"}]}]}'. Resposta 201 com ID do post.

Por que aprender:

Se curl funciona, qualquer linguagem funciona. É o teste irredutível de que a API está acessível e a key é válida.

Conceitos-chave:

Header Authorization sem "Bearer", integration ID obtido em GET /integrations, type=schedule|now|draft, date em ISO 8601 UTC.

O que é:

Em Settings → Webhooks, cadastre uma URL HTTPS sua. Postiz POSTa JSON quando eventos ocorrem: post.published (com URL final na rede), post.failed (com mensagem de erro), post.scheduled.

Por que aprender:

Polling /posts/:id pra saber se publicou é gambiarra. Webhook = sua app reage em tempo real ao sucesso/falha sem desperdiçar request.

Conceitos-chave:

Retry com backoff exponencial em 5xx, assinatura HMAC opcional, idempotency key no payload, timeout 10s.

O que é:

No n8n, HTTP Request node com método POST, URL da sua instância, header Authorization (credential reutilizável), body JSON dinâmico via expressões. Make idem com módulo HTTP. Zero plugin específico necessário — REST puro.

Por que aprender:

É o caminho mais rápido para automatizar "post toda terça às 10h com últimos posts do RSS" sem escrever uma linha de código.

Conceitos-chave:

Credential type "Header Auth", trigger por cron/RSS/Airtable, tratamento de erro com IF node, logs em Supabase.

O que é:

Pipeline típico: (1) seu CMS/Notion/Airtable cria conteúdo → (2) trigger (webhook/cron) chama POST /public/v1/posts com agendamento → (3) Postiz coloca na fila Redis → (4) na hora marcada publica em N redes → (5) webhook avisa sua app com URL final → (6) sua app guarda histórico.

Por que aprender:

É a arquitetura que separa "ferramenta isolada" de "componente do meu stack". Vale para SaaS, blog automation, agência multi-cliente.

Conceitos-chave:

Idempotência por external_id, dead-letter queue para falhas persistentes, retry com circuit breaker, observabilidade end-to-end (request_id propagado).

Ver Completo
← Trilha 1: Fundamentos Início Trilha 3: Redes →