Deploy técnico (self-host)
Suba a Next Wiki com Docker — variáveis de ambiente, banco, storage e IA.
Self-host com Docker
A Next Wiki roda como uma única imagem (o frontend é servido pelo próprio
backend .NET, na mesma porta). Você só precisa de Docker e um PostgreSQL
acessível. A configuração é feita por variáveis de ambiente padronizadas
(SECRET_KEY, DATABASE_URL, URL, REDIS_URL, SMTP_*…).
Pré-requisitos
- Docker 24+ (e Docker Compose v2)
- PostgreSQL 14+ — pode ser um banco já existente; a Next Wiki usa um
database próprio (ex.:
next_wiki) e nunca dropa o banco (migrations comIF NOT EXISTS). - Um endpoint de IA compatível com OpenAI (opcional, mas recomendado): OpenAI, um gateway litellm ou Ollama local.
Requisitos de hardware
A imagem é enxuta e a aplicação reusa um pool de conexão “quente” com o banco — roda confortável em máquinas pequenas.
| Cenário | CPU | RAM | Disco |
|---|---|---|---|
| Mínimo (time pequeno) | 1 vCPU | 1 GB | 10 GB |
| Recomendado (app + Postgres na mesma VM) | 2 vCPU | 2 GB | 20 GB+ |
| Equipe grande / muitos anexos | 2–4 vCPU | 4 GB | conforme o conteúdo |
Mantenha backend e PostgreSQL na mesma região/rede. Cada query paga a latência de rede até o banco; com eles juntos, as consultas ficam em poucos milissegundos.
Variáveis de ambiente
| Variável | Obrigatória | Descrição |
|---|---|---|
SECRET_KEY | sim | Segredo que assina o JWT da sessão. ≥ 32 caracteres. |
DATABASE_URL | sim | Conexão Postgres: postgresql://usuario:senha@host:5432/next_wiki. |
URL | sim | URL pública da wiki (usada em links de convite/e-mail). |
PORT | não | Porta que a aplicação escuta. Padrão 8080. |
BOOTSTRAP_ADMIN_EMAIL | não | E-mail que vira o 1º admin no primeiro boot (via magic link). |
FILE_STORAGE_LOCAL_ROOT_DIR | não | Raiz do storage local (markdown + ícones). Padrão /app/data. |
REDIS_URL | não | Cache distribuído. Vazio = cache em memória. Ex.: redis://host:6379. |
SMTP_HOST … SMTP_SECURE | não | Envio de e-mail (magic link, convites). Sem SMTP_HOST, e-mail vira no-op. |
OIDC_ISSUER_URL, OIDC_CLIENT_ID, OIDC_CLIENT_SECRET | não | SSO via OIDC (Keycloak, etc). Vazio = só magic link. |
IA_MODELO, LITELLM_KEY | não | Modelo padrão e chave do endpoint de IA (OpenAI-compat). |
OTEL_EXPORTER_OTLP_ENDPOINT | não | Observabilidade OpenTelemetry. Vazio = desligado. |
docker-compose.yml
services:
app:
image: nexttag/next-wiki:latest
environment:
SECRET_KEY: "troque-por-um-segredo-com-mais-de-32-chars"
DATABASE_URL: "postgresql://admin:senha@host.docker.internal:5432/next_wiki"
URL: "https://wiki.suaempresa.com"
BOOTSTRAP_ADMIN_EMAIL: "voce@suaempresa.com"
# IA (opcional) — endpoint OpenAI-compat (litellm/OpenAI/Ollama)
IA_MODELO: "gpt-4o-mini"
LITELLM_KEY: "sua-chave"
ports:
- "5210:8080" # host:container
volumes:
- nextwiki_data:/app/data # markdown dos documentos + ícones
extra_hosts:
- "host.docker.internal:host-gateway"
volumes:
nextwiki_data:
Suba com:
docker compose up -d
Banco de dados (PostgreSQL)
A Next Wiki guarda os metadados (usuários, permissões, árvore, versões) no
PostgreSQL. Você aponta para ele pela variável DATABASE_URL:
postgresql://usuario:senha@host:5432/next_wiki
└ usuário └ senha └ host └ porta └ database
As migrations rodam automaticamente no boot e nunca dropam o banco
(IF NOT EXISTS / ADD COLUMN IF NOT EXISTS).
Opção A — usar um Postgres que você já tem
Aponte DATABASE_URL para o seu servidor e crie só o database:
CREATE DATABASE next_wiki;
De dentro do container, use host.docker.internal como host (é o caso do
compose acima).
Opção B — subir o Postgres junto (tudo em um compose)
Se você não tem um Postgres, suba um no próprio docker-compose — o host do
banco passa a ser o nome do serviço (db):
services:
app:
image: nexttag/next-wiki:latest
environment:
SECRET_KEY: "troque-por-um-segredo-com-mais-de-32-chars"
DATABASE_URL: "postgresql://nextwiki:senha@db:5432/next_wiki"
URL: "https://wiki.suaempresa.com"
BOOTSTRAP_ADMIN_EMAIL: "voce@suaempresa.com"
ports:
- "5210:8080"
volumes:
- nextwiki_data:/app/data
depends_on:
db:
condition: service_healthy
db:
image: postgres:16-alpine
environment:
POSTGRES_USER: nextwiki
POSTGRES_PASSWORD: senha
POSTGRES_DB: next_wiki # cria o database no primeiro boot
volumes:
- nextwiki_pg:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U nextwiki -d next_wiki"]
interval: 10s
timeout: 5s
retries: 5
volumes:
nextwiki_data:
nextwiki_pg:
O depends_on com healthcheck garante que a app só sobe quando o banco estiver
pronto. O volume nextwiki_pg preserva os dados do banco entre reinícios —
inclua-o no backup (ou use pg_dump, veja abaixo).
Primeiro acesso
- Abra a
URLconfigurada. - Informe o e-mail definido em
BOOTSTRAP_ADMIN_EMAIL— ele recebe o magic link (ou, sem SMTP, o link aparece nos logs do container). - Ao entrar, você já é admin do workspace. Convide o time e organize as coleções.
HTTPS e proxy reverso
A imagem serve HTTP na porta interna — em produção, coloque-a atrás de um
proxy com TLS. A aplicação já honra os cabeçalhos X-Forwarded-*, então
basta o proxy encaminhá-los; os links e cookies de sessão saem com o esquema
https corretamente.
Caddy (TLS automático via Let’s Encrypt):
wiki.suaempresa.com {
reverse_proxy localhost:5210
}
Cloudflare Tunnel (sem abrir portas):
ingress:
- hostname: wiki.suaempresa.com
service: http://localhost:5210
- service: http_status:404
Defina sempre a variável
URLcom o endereço público https — é ela que monta os links de convite/e-mail e valida a origem das requisições.
Verificar se está no ar
# deve responder 200 (a raiz serve o app)
curl -I https://wiki.suaempresa.com
# acompanhar o boot e as migrations
docker compose logs -f app
Para um healthcheck no Docker, adicione ao serviço app:
healthcheck:
test: ["CMD", "wget", "-qO-", "http://localhost:8080/"]
interval: 30s
timeout: 5s
retries: 3
Storage e dados
O corpo dos documentos é guardado como markdown em
FILE_STORAGE_LOCAL_ROOT_DIR (padrão /app/data), junto dos ícones. Mantenha
esse diretório em um volume para não perder conteúdo entre atualizações. Os
metadados (usuários, permissões, árvore) ficam no PostgreSQL.
Produção: escala e segurança
- Rate limiting já vem embutido — a aplicação limita requisições por padrão, sem configuração extra.
- Cabeçalhos de segurança e compressão de resposta também são aplicados automaticamente.
- Edição em tempo real: a colaboração usa WebSocket (SignalR). Para uma
instância, funciona sem nada a mais. Para rodar várias instâncias atrás de
um balanceador, configure
REDIS_URL— o Redis vira o backplane que sincroniza as conexões entre os nós (e também serve de cache distribuído). - Observabilidade: defina
OTEL_EXPORTER_OTLP_ENDPOINTpara enviar logs/traces (OpenTelemetry) ao seu coletor (Grafana/Loki, etc).
Atualizar
# 1. backup do banco e do volume (ver abaixo)
docker compose pull
docker compose up -d # migrations rodam automaticamente no boot
Backup
# Banco (metadados)
pg_dump "postgresql://admin:senha@localhost:5432/next_wiki" > next_wiki.sql
# Conteúdo (markdown + ícones)
docker run --rm -v nextwiki_data:/data -v "$PWD":/backup alpine \
tar czf /backup/nextwiki_data.tgz -C /data .
Solução de problemas
| Sintoma | Causa provável | O que fazer |
|---|---|---|
| Container não sobe e some | SECRET_KEY ausente/curto | Defina SECRET_KEY com ≥ 32 caracteres. |
password authentication failed / sem conexão | DATABASE_URL errada ou banco inacessível | Confira host/porta/credenciais; de dentro do container use host.docker.internal. |
| Não chega o magic link | SMTP não configurado | Sem SMTP_HOST, o link aparece nos logs (docker compose logs app). |
| Login cai/redireciona errado atrás de proxy | URL ou X-Forwarded-* | Use URL com https público e garanta que o proxy encaminha os cabeçalhos. |
| Conteúdo sumiu após atualizar | volume não persistido | O /app/data precisa estar em um volume nomeado. |
| IA não responde | endpoint/chave de IA | Verifique IA_MODELO e a chave; o endpoint precisa ser compatível com OpenAI. |
Pronto — uma instância sua, com os dados sob seu controle e a IA apontando para o provedor que você escolher.