Pular para o conteúdo
miblo

Servidor próprio

O servidor do Miblo Remote, para subir no seu próprio host. Com ele, o celular e o computador conversam só pelo seu servidor, nunca pelo miblo.ai. É opcional e de graça, para quem sabe hospedar.

Baixar

Versão 1.3.0

Distribuído só pelo miblo.ai e assinado com a mesma chave das atualizações do Miblo (Ed25519). Confira a assinatura antes de usar: o comando está logo abaixo, em Baixar e conferir.

Licença AGPL-3.0, no pacote.

Prefere o Git? O código-fonte também está no GitHub: github.com/marcus-campos/miblo-relay

Guia do servidor

O README do pacote desta versão.

O servidor do celular do Miblo, para você subir no seu próprio host: o relay das sessões, a conta em que os seus celulares entram, o registro de celulares e o app do celular (PWA). É o mesmo protocolo que o plugin do Miblo e o miblo.ai usam, então tudo do Miblo+ que passa pelo celular (histórico, respostas, aprovações, tarefas remotas) funciona aqui, de graça e sem licença, para quem subir o próprio servidor.

Privacidade

O Miblo já é cifrado de ponta a ponta: as chaves nascem no seu computador, chegam a cada celular seladas para a chave daquele celular, só depois que você digita no computador o código de 6 dígitos que o celular mostra, e o servidor só repassa dados cifrados. Um servidor malicioso (o miblo.ai ou este) não lê nada, não coloca um celular dele no lugar do seu e não age no seu computador.

O que sobra é o código do app do celular: ele é uma página web, e quem serve a página roda código com as chaves do celular. No miblo.ai, você confia no que o miblo.ai serve. No seu servidor, o app é o que você compilou deste código (ou uma versão cujos hashes você conferiu), servido por você. Isso tira a confiança no JavaScript servido pelo miblo.ai. Detalhes no modelo de ameaças (docs/threat-model.md).

Enquanto o seu servidor estiver configurado, o plugin não manda nada do celular nem da conta para o miblo.ai (ele só continua lendo do miblo.ai o manifesto assinado de atualizações).

Baixar e conferir

O download é pelo miblo.ai, em https://miblo.ai/dl/relay/, ao lado do firmware e dos instaladores (quem prefere o Git encontra o código em https://github.com/marcus-campos/miblo-relay), e vem dos instaladores, e assinado com a mesma chave das releases do Miblo (Ed25519). A versão mais nova está em https://miblo.ai/dl/extras/latest.json; a página miblo.ai/docs/servidor-proprio mostra este guia e o link dela.

V=1.0.0   # a versão mais nova: https://miblo.ai/dl/extras/latest.json
curl -fLO https://miblo.ai/dl/relay/miblo-relay-$V.tar.gz
curl -fLO https://miblo.ai/dl/relay/miblo-relay-$V.tar.gz.sig
node -e 'const c=require("crypto"),fs=require("fs"),f=process.argv[1],k=c.createPublicKey({key:{kty:"OKP",crv:"Ed25519",x:Buffer.from("LGtuUvDA506N8iD1tolbQzWAJBb9hUerW0OH4C2pBek=","base64").toString("base64url")},format:"jwk"});const ok=c.verify(null,fs.readFileSync(f),k,Buffer.from(fs.readFileSync(f+".sig","utf8").trim(),"base64"));console.log(ok?"assinatura OK":"ASSINATURA INVÁLIDA: não use este arquivo");process.exit(ok?0:1)' miblo-relay-$V.tar.gz
tar -xzf miblo-relay-$V.tar.gz && cd miblo-relay-$V

A chave pública (LGtuUvDA506N8iD1tolbQzWAJBb9hUerW0OH4C2pBek=) é a mesma que o plugin do Miblo usa para conferir as atualizações. https://miblo.ai/dl/relay/SHA256SUMS (assinado em SHA256SUMS.sig) traz o SHA-256 de cada versão publicada.

Subir em 3 passos (Docker)

Você precisa de uma máquina com Docker, um nome DNS apontando para ela e as portas 80 e 443 abertas (o Caddy pega o certificado TLS sozinho).

1. Configurar, dentro da pasta baixada e conferida acima:

cd deploy/docker
cp .env.example .env   # coloque o seu domínio em RELAY_DOMAIN

2. Subir

docker compose up -d --build
docker compose logs relay   # mostra o código de configuração e a impressão digital do servidor

3. Criar a sua conta: abra https://seu-dominio/conta, use o código de configuração, crie a senha e adicione um segundo fator (passkey recomendada, ou app autenticador). Gere os códigos de recuperação.

Depois, no computador: apontar o plugin para o seu servidor. Sem Docker: npm ci && npm run build && PUBLIC_ORIGIN=https://seu-dominio node dist/server.mjs (Node 22.13+ ou 23.4+, que têm node:sqlite) atrás de qualquer proxy com TLS.

Na sua própria conta Cloudflare

Roda como um Worker na sua conta Cloudflare (o plano gratuito basta para uma pessoa), com D1 e Durable Objects:

npm ci
cp deploy/cloudflare/wrangler.jsonc.example deploy/cloudflare/wrangler.jsonc
cd deploy/cloudflare
npx wrangler d1 create miblo-relay          # coloque o database_id no wrangler.jsonc
npx wrangler d1 migrations apply miblo-relay --remote
cd ../.. && npm run build:app && npm run cf:secrets   # mostra o código de configuração e a impressão digital
cd deploy/cloudflare && npx wrangler deploy

Depois, o passo 3 acima (https://seu-endereço/conta).

Apontar o seu computador para ele

No seu terminal (nunca por um agente de IA), com o plugin do Miblo na versão que tem miblo server:

miblo server set https://seu-dominio

O Miblo lê a chave de identidade do servidor, mostra a impressão digital (compare com a que o seu servidor mostrou no log: docker compose logs relay ou node dist/server.mjs fingerprint) e pede o código que aparece na tela do seu Miblo. No app Miblo do computador: Ajustes › Servidor do celular. Trocar de servidor desvincula este computador e desliga o celular no servidor antigo; depois:

miblo account link   # confirme o código em https://seu-dominio/plus/link
miblo phone on

No celular, abra https://seu-dominio/app, entre na sua conta e permita o celular no computador com o código que ele mostra. miblo server mostra para onde aponta; miblo server reset volta para o miblo.ai (também com o código do Miblo).

Configuração

VariávelObrigatóriaO que é
PUBLIC_ORIGINsimO endereço https do servidor, só a origem (https://relay.exemplo.com). É a origem do app, o relying party das passkeys e o endereço do link de vinculação. Nunca vem da requisição.
TRUSTED_PROXYatrás de proxyOs endereços ou faixas (CIDR) do seu proxy, separados por vírgula (172.30.247.0/24). Só de uma conexão vinda deles o endereço do cliente é a última entrada do X-Forwarded-For (a que o proxy colocou). Só usado como chave de limite de taxa. Não defina sem um proxy na frente.
RELAY_VAPID_SUBJECTnãoContato enviado aos serviços de push (mailto:voce@exemplo.com); sem ele, o endereço do servidor.
SESSION_SECRET, MFA_KEY, SERVER_IDENTITY_KEY, RELAY_VAPID_PUBLIC_KEY, RELAY_VAPID_PRIVATE_KEY, SETUP_TOKENnão (Node) / sim (Cloudflare)No Node, os que você não definir são criados uma vez e guardados em secrets.json (0600), na pasta $MIBLO_RELAY_SECRETS_DIR. Na Cloudflare, npm run cf:secrets cria e guarda todos.
MIBLO_RELAY_DATAnãoPasta do banco (Docker: /data).
MIBLO_RELAY_SECRETS_DIRnãoPasta do secrets.json (padrão: MIBLO_RELAY_DATA; Docker: /secrets, um volume à parte, fora dos backups do banco).
PORT, HOSTnãoOnde o Node escuta (padrão 0.0.0.0:8787).

Comandos do Node: node dist/server.mjs check (confere a configuração), fingerprint, setup-token (o código de configuração vale para uma configuração só; depois de usado, este comando gera outro, para refazer uma configuração abandonada), reset-account (perdeu todos os fatores: apaga fatores e sessões e gera um novo código de configuração; computadores e celulares continuam). Na Cloudflare, para o mesmo efeito, apague as linhas de mfa_* e sessions com wrangler d1 execute e defina um novo código com npx wrangler secret put SETUP_TOKEN (um valor aleatório longo, como openssl rand -base64 24).

Atualizar

Baixe e confira a versão nova como em Baixar e conferir, copie para ela o seu deploy/docker/.env (na Cloudflare, o seu deploy/cloudflare/wrangler.jsonc) e, na pasta nova:

cd deploy/docker && docker compose up -d --build

Os volumes do Docker (banco e segredos) continuam os mesmos: o projeto do Compose leva o nome da pasta (docker), igual nas duas versões. As migrações do banco rodam sozinhas ao subir (Node). Na Cloudflare: npm ci && npx wrangler d1 migrations apply miblo-relay --remote && npm run build:app && npx wrangler deploy. Acompanhe as versões em https://miblo.ai/dl/extras/latest.json: correções de segurança são avisadas na página miblo.ai/docs/servidor-proprio. Faça backup do volume relay-data (Docker) antes de atualizar.

Segurança

  • Leia o modelo de ameaças (docs/threat-model.md): um operador malicioso tem o mesmo poder que um miblo.ai malicioso, que o protocolo já tolera.

  • Uma conta só, segundo fator obrigatório; a senha sozinha nunca entra. Senha com PBKDF2-SHA-256 (600.000 iterações no Node; 100.000 na Cloudflare, o máximo que um Worker permite). Senhas erradas bloqueiam só a rede de onde vieram, por 15 minutos, com a mesma resposta de um nome errado.

  • O plugin fixa a chave de identidade do servidor na primeira vez (TOFU) e exige uma assinatura nova dela antes de usar o servidor; se a chave mudar, nada é enviado até você aceitar a nova com miblo server set (e o código do Miblo).

  • Guarde secrets.json (ou os segredos do Worker) longe de backups que outros leiam.

  • Encontrou uma falha? Escreva para contato@miblo.ai (assunto "Security"), em particular. Não a publique antes da correção.

Builds reproduzíveis

O build é determinístico (imagem base fixada por digest, dependências do package-lock.json). O Docker grava dist/HASHES.txt: o SHA-256 de cada arquivo servido e do servidor, e um hash do conjunto (build …). Para conferir o que roda:

docker compose exec relay tail -1 dist/HASHES.txt   # o que está rodando
npm ci && npm run build && npm run hashes | tail -1  # o que este código gera

Os dois precisam ser iguais: o que roda é o que este código, conferido pela assinatura, gera.

Licença

AGPL-3.0 (LICENSE): quem oferecer este servidor modificado como serviço precisa publicar o código das modificações. O dono do projeto pode trocar a licença enquanto for o único autor.

Voltar para a documentação