Rodando seu próprio retransmissor
O retransmissor leva os conteúdos criptografados entre os seus dispositivos. Ele nunca vê nada além de um hash de sala e texto cifrado, e não guarda nada — mas você não precisa acreditar nisso, porque pode rodar o seu. É um arquivo Python, sem banco de dados.
Rode
docker run -p 8000:8000 ghcr.io/akshaynikhare/realtimeclipboard-relay
Ou a partir de um clone, sem contêiner nenhum:
pip install -r backend/requirements.txt
python -m uvicorn main:app --app-dir backend --port 8000
É o retransmissor inteiro. Sem banco de dados, sem volume, sem passo de migração e sem nada para fazer backup — cada sessão vive na memória e some quando o processo termina, o que é o projeto e não uma limitação.
Confira se funcionou
curl http://localhost:8000/health
Ele responde com o identificador da instância. Esse campo não é enfeite: é assim que um cliente percebe que foi balanceado para outra réplica no meio da sessão, que é a falha com a qual este projeto precisa tomar cuidado — veja a seção sobre réplicas mais abaixo.
Aponte o aplicativo para ele
- Abra o aplicativo e vá em Configurações → Retransmissor.
- Digite a URL do seu retransmissor —
ws://localhost:8000para um teste local,wss://clip.example.compara valer. - A barra de status mostra Conectado assim que ele responder. Faça o mesmo num segundo dispositivo e sincronize um conteúdo entre os dois; nada passou pelo retransmissor público.
O cliente de linha de comando aceita --relay ou
REALTIMECLIPBOARD_RELAY para a mesma coisa.
TLS e um nome de domínio de verdade
cd deploy
REALTIMECLIPBOARD_DOMAIN=clip.example.com docker compose up -d
O diretório deploy tem um arquivo compose que põe o Caddy na frente do retransmissor e obtém o certificado automaticamente, e ao lado dele um chart do Helm para Kubernetes.
Na prática, TLS não é opcional. Os navegadores só expõem
crypto.subtle em contexto seguro, então uma página servida
por HTTP puro num endereço de rede local não consegue nem derivar uma
chave — o aplicativo não tem como funcionar ali, faça o retransmissor o
que fizer.
Antes de escalar
Fixe as réplicas em uma, ou dê um Redis para ele. Uma sala fica na
memória do processo que a atende, então duas réplicas atrás de um
balanceador round-robin colocam as duas metades de uma sessão em máquinas
diferentes, e nenhuma enxerga a outra. Isso aparece como conteúdos que
simplesmente não chegam, o que parece um bug de cliente e não é. O chart
do Helm recusa replicaCount > 1 sem Redis exatamente por
esse motivo.
As notas de auto-hospedagem
cobrem as variáveis de ambiente e o caminho de alta disponibilidade por
inteiro.
Quando não funciona
Conectado, mas nada chega
Quase sempre mais de uma réplica sem estado compartilhado — veja acima.
Compare o identificador de /health em cada dispositivo: se
forem diferentes, a resposta é essa.
O aplicativo não alcança o retransmissor
Duas suspeitas. A Content-Security-Policy da própria página lista as
origens de retransmissor a que ela pode se conectar, então uma cópia
auto-hospedada do site estático precisa do connect-src
atualizado no index.html, no app.html e em cada
página dentro de src/pages/. E se você estiver usando o site
hospedado com o seu próprio retransmissor, a política de lá não vai
permitir — hospede as duas metades.
Conecta e cai, repetidamente
Um proxy reverso que não encaminha os upgrades de WebSocket. O cliente
então cai para server-sent events mais POST e continua funcionando, mais
devagar, e é por isso que isso aparece como lentidão e não como falha.
Encaminhe Upgrade e Connection.
Uma sessão ociosa some
As salas são recolhidas quando ficam vazias. Isso é deliberado — um retransmissor que não guarda nada não tem nada a vazar.
Desligando
docker compose down # or: docker rm -f <container>
Não há dado nenhum para apagar. Tudo o que o retransmissor guardou estava na memória, e era texto cifrado.
As notas operacionais completas, incluindo a tabela de variáveis de ambiente e o caminho de alta disponibilidade: docs/SELF-HOSTING.md. Todas as plataformas: o guia de instalação. Algo errado ou desatualizado aqui? Abra uma issue.