Saltar para o conteúdo principal

Guia de Auto-Alojamento

Execute a sua própria instância do Campbooks com Docker em poucos minutos. Este guia cobre a configuração completa: a pilha, os segredos necessários e como configurar cada integração externa.

Só quer experimentar localmente? Vá diretamente para Início rápido. A executá-lo num servidor a sério? Leia também Executar em produção.

O que obtém

docker compose up executa três contentores:

ServiçoO que é
postgresPostgreSQL com a extensão pgvector (obrigatória)
webA aplicação Rails (Puma atrás do Thruster)
workerTarefas em segundo plano — digitalização de email, IA, indexação (Solid Queue)

O Postgres contém tudo: dados da aplicação, cache, tarefas e Action Cable (via os adaptadores Solid), mais embeddings vetoriais para pesquisa semântica (pgvector). Um quarto serviço, opensearch, é opcional e apenas suporta o autocompletar de texto completo de contactos — consulte Pesquisa.

Os ficheiros carregados (anexos de email guardados como Documentos) ficam num volume Docker local por omissão, ou em armazenamento de objetos compatível com S3, se configurado.

Pré-requisitos

  • Docker e o plugin Docker Compose (Docker Desktop, ou Docker Engine ≥ 24 com docker compose)
  • Cerca de 2 GB de RAM livres para a pilha padrão (adicione ~1 GB se ativar o OpenSearch)
  • openssl na sua máquina (já presente no macOS/Linux) para gerar segredos
  • Opcional, para uma implementação real: um nome de domínio e um proxy reverso com terminação TLS (Caddy, Traefik, nginx)

Início rápido

git clone https://github.com/notacamp/campbooks.git
cd campbooks

cp .env.example .env
bin/generate-secrets # preenche SECRET_KEY_BASE, as chaves de encriptação AR e a palavra-passe da BD

# (opcional) edite .env para adicionar uma chave de IA e as integrações que pretende
docker compose up -d --build

# acompanhe o arranque; o primeiro boot cria as bases de dados e executa as migrações
docker compose logs -f web

Depois abra http://localhost:3000 e registe a primeira conta — numa instância auto-alojada o registo está aberto, e o primeiro utilizador cria o espaço de trabalho.

O primeiro arranque também cria um espaço de trabalho de demonstração com credenciais admin@example.com / changeme123 (e partner@example.com). Altere essa palavra-passe após o primeiro início de sessão, ou defina SEED_PASSWORD em .env antes do primeiro arranque. Não quer os dados de demonstração? Basta registar a sua própria conta e apagar o espaço de trabalho de demonstração.

A aplicação funciona totalmente sem chaves de API externas; as funcionalidades de IA e as ligações de caixas de correio ativam-se à medida que adicionar as credenciais (abaixo).

Para parar: docker compose down (adicione -v para também apagar a base de dados/ficheiros carregados).

Configuração

Toda a configuração são variáveis de ambiente em .env. bin/generate-secrets trata dos segredos obrigatórios; tudo o resto é opcional. A lista anotada encontra-se em .env.example.

Obrigatórias (geradas para si)

VariávelNotas
SECRET_KEY_BASEChave de sessão/assinatura do Rails. openssl rand -hex 64
ACTIVE_RECORD_PRIMARY_KEYEncripta tokens OAuth e chaves de IA em repouso. openssl rand -hex 16
ACTIVE_RECORD_DETERMINISTIC_KEYIdem
ACTIVE_RECORD_KEY_DERIVATION_SALTIdem
CAMPBOOKS_DATABASE_PASSWORDPalavra-passe do Postgres incluído

Não precisa de config/master.key — o auto-alojamento lê SECRET_KEY_BASE a partir do ambiente.

Obrigatórias (definidas por si)

VariávelPredefiniçãoNotas
APP_HOSTlocalhostO hostname pelo qual acede à aplicação. Tem de corresponder ao cabeçalho Host (localhost, um IP ou o seu domínio) — outros hosts são rejeitados por segurança.
FORCE_SSLfalseMantenha false para uso local em HTTP simples. Defina true apenas atrás de um proxy TLS (consulte Produção).
SELF_HOSTED1Registo aberto + lê chaves de IA a partir do ambiente.

Integrações externas

Todas as integrações são opcionais. Adicione as que pretender; ignore as restantes.

Para cada fornecedor OAuth, tem de registar uma aplicação na consola desse fornecedor e colocar na lista de permissões o URL de callback, que é <url-da-sua-aplicação>/oauth/<fornecedor>/callback — por exemplo, http://localhost:3000/oauth/gmail/callback localmente, ou https://app.example.com/oauth/gmail/callback em produção.

Fornecedores de IA

A IA é o que torna o Campbooks no Campbooks (triage, o assistente Scout, respostas rascunhadas, análise de documentos, pesquisa semântica) — mas é tudo opcional e desativado até adicionar uma chave. Pode definir chaves aqui para toda a instância, ou deixar cada utilizador introduzir a sua própria em Definições → IA (armazenadas encriptadas por espaço de trabalho).

VariávelAtiva
OPENAI_API_KEYIA de texto + análise de documentos/visão + embeddings (pesquisa semântica). A chave única mais completa.
ANTHROPIC_API_KEYIA de texto (Claude)
MISTRAL_API_KEYIA de texto (alojado na UE)
DEEPSEEK_API_KEYIA de texto
GEMINI_API_KEYIA de texto + embeddings
  • Para o assistente/triage: defina qualquer fornecedor de texto.
  • Para análise de anexos/documentos e a melhor pesquisa: defina OPENAI_API_KEY.
  • Sem fornecedor de embeddings (OpenAI ou Gemini), a pesquisa reverte para correspondência por palavras-chave.

Google — Gmail e Calendário

Permite que os utilizadores iniciem sessão com o Google e liguem uma caixa de correio Gmail (que também sincroniza o Google Calendar com a mesma autorização).

  1. Google Cloud Console → crie um projeto → APIs & Services → Credentials → OAuth client ID (tipo: Web application).
  2. Ative a Gmail API e a Google Calendar API para o projeto.
  3. Adicione o URI de redirecionamento: <url-da-sua-aplicação>/oauth/gmail/callback.
  4. Defina GOOGLE_CLIENT_ID e GOOGLE_CLIENT_SECRET.

Google Drive — "Enviar para o Drive"

A exportação interativa para o Drive usa o âmbito completo drive, um âmbito restrito do Google, pelo que precisa da sua própria aplicação OAuth verificada separadamente.

  1. Crie um segundo cliente OAuth (ou um projeto separado).
  2. Adicione o âmbito https://www.googleapis.com/auth/drive e o URI de redirecionamento <url-da-sua-aplicação>/oauth/google/callback.
  3. Defina GOOGLE_DRIVE_CLIENT_ID e GOOGLE_DRIVE_CLIENT_SECRET.

Zoho Mail

  1. Zoho API ConsoleServer-based Application.
  2. URI de redirecionamento: <url-da-sua-aplicação>/oauth/zoho/callback.
  3. Defina ZOHO_CLIENT_ID, ZOHO_CLIENT_SECRET e ZOHO_REGION (eu, com, in, au, jp — corresponda ao seu centro de dados Zoho).

Microsoft 365 / Outlook

  1. Centro de administração do EntraRegistos de aplicações → Novo registo. Tipos de conta suportados: Contas em qualquer diretório organizacional (contas profissionais/escolares; a aplicação usa o endpoint /organizations/).
  2. Adicione um URI de redirecionamento Web: <url-da-sua-aplicação>/oauth/microsoft/callback.
  3. Crie um segredo de cliente.
  4. Defina MICROSOFT_CLIENT_ID, MICROSOFT_CLIENT_SECRET e ENABLE_MICROSOFT_MAILBOX=1 (este último revela o botão "Ligar Microsoft 365").

Notion — "Enviar para o Notion"

  1. notion.so/my-integrations → nova integração, tipo Public, com capacidades de leitura/inserção de conteúdo.
  2. URI de redirecionamento: <url-da-sua-aplicação>/oauth/notion/callback.
  3. Defina NOTION_CLIENT_ID e NOTION_CLIENT_SECRET.

Se deixar estas variáveis por definir, os utilizadores podem ainda assim ligar o Notion colando um token de integração interna nas Definições.

Email de saída (SMTP)

Sem SMTP, a aplicação não envia email (códigos OTP de registo, notificações e relatórios são ignorados — aceitável para um teste de utilizador único, mas vai querer isso para uso real).

SMTP_ADDRESS=smtp.example.com
SMTP_PORT=587
SMTP_USERNAME=you@example.com
SMTP_PASSWORD=your_smtp_password
MAILER_FROM=Campbooks <no-reply@example.com>

Armazenamento de ficheiros (S3)

Por omissão, os ficheiros carregados ficam no volume Docker storage. Para usar armazenamento de objetos (recomendado se executar múltiplas réplicas web ou quiser cópias de segurança mais fáceis), defina:

S3_ACCESS_KEY_ID=...
S3_SECRET_ACCESS_KEY=...
S3_BUCKET=campbooks-storage
S3_REGION=eu-central-1
# Para fornecedores não-AWS (MinIO, Hetzner, Backblaze B2, ...):
S3_ENDPOINT=https://...
S3_FORCE_PATH_STYLE=true

Pesquisa (OpenSearch)

O OpenSearch é opcional e apenas suporta o autocompletar de texto completo de contactos. A pesquisa de email, pesquisa de documentos e a paleta Cmd+K usam todas Postgres + pgvector e funcionam sem ele; a pesquisa de contactos reverte para correspondência SQL. Para ativá-lo:

# em .env
OPENSEARCH_URL=http://opensearch:9200
docker compose --profile search up -d

Monitorização de erros e push

  • SENTRY_DSN — um DSN compatível com Sentry (por exemplo, GlitchTip auto-alojado). Desativado se não definido.
  • APNS_* / FCM_* — apenas necessários se compilar as aplicações nativas iOS/Android. Desativados se não definidos.

Executar em produção

Para qualquer uso além do local, termine o TLS com um proxy reverso e ative o SSL.

  1. Aponte um domínio para o seu servidor e defina, em .env:
    APP_HOST=app.example.com
    FORCE_SSL=true
    WEB_PORT=3000
  2. Coloque um proxy com terminação TLS à frente. Com o Caddy (HTTPS automático) é apenas:
    app.example.com {
    reverse_proxy localhost:3000
    }
    O proxy fala HTTPS para o mundo e encaminha para o contentor na porta :3000; FORCE_SSL=true faz o Rails emitir links https, definir cookies seguros e enviar HSTS. (O endpoint de saúde /up mantém-se acessível em HTTP simples para sondagens.)
  3. docker compose up -d --build.

Não exponha a aplicação em HTTP simples na internet. Com FORCE_SSL=false, as sessões e os cookies viajam sem encriptação. Utilize sempre um proxy TLS em produção.

Cópias de segurança

Dois elementos mantêm estado: o volume do Postgres e os ficheiros carregados.

# Base de dados (a BD da aplicação; cache/queue/cable são regeneráveis)
docker compose exec -T postgres pg_dump -U campbooks_app cb_primary | gzip > campbooks-$(date +%F).sql.gz

# Ficheiros carregados (apenas se usar armazenamento em disco local, não S3)
docker run --rm -v campbooks_storage:/data -v "$PWD":/backup alpine \
tar czf /backup/campbooks-storage-$(date +%F).tar.gz -C /data .

Guarde as cópias de segurança fora do servidor. Se usar S3 para armazenamento, apenas a base de dados precisa de cópia de segurança aqui.

Atualizações

git pull
docker compose up -d --build # o entrypoint executa as migrações no arranque

Faça uma cópia de segurança da base de dados primeiro. As migrações executam automaticamente quando o contentor web arranca.

Consola e tarefas

docker compose exec web bin/rails console
docker compose exec web bin/rails db:seed # dados de demonstração opcionais / login

Resolução de problemas

Cada pedido redireciona para https:// e falha. FORCE_SSL está ativo mas não há proxy TLS. Defina FORCE_SSL=false para uso local, ou coloque um proxy TLS à frente para produção.

"Blocked hosts" / 403 em todas as páginas. APP_HOST não corresponde à forma como está a aceder à aplicação. Defina-o com o hostname/IP exato na barra de endereços e recrie os contentores.

O web reinicia repetidamente com erro de base de dados/extensão. Certifique-se de que o serviço postgres usa a imagem pgvector/pgvector incluída (uma imagem postgres comum não consegue fazer CREATE EXTENSION vector). Se a trocou, reverta.

O worker regista erros logo após arrancar. Aguarda que o web termine as migrações; os erros transitórios durante o primeiro arranque estabilizam assim que o web estiver saudável.

Segredo obrigatório em falta no docker compose up. Saltou o bin/generate-secrets, ou falta uma chave no .env. Execute novamente o script.