Plataformas
Servidor independente
O servidor independente roda o Runlight como um app próprio para quantos sites você quiser, com login, links curtos nos seus próprios domínios e relatórios por email.
O servidor independente é o Runlight empacotado como um app próprio. Ele serve para um site cujo app não consegue rodar o Runlight, e reúne vários sites em um só painel. Ele roda o mesmo código da biblioteca, então relatórios, metas, links curtos e relatórios por email funcionam todos do mesmo jeito.
Esta página trata do servidor em Node. Python, Ruby, Go, Java e .NET têm cada um o seu próprio servidor, que funciona do mesmo jeito, e numa hospedagem que roda PHP sem Node, o drop-in em PHP faz o mesmo trabalho.
Inicie o servidor
Com Docker, rode isto.
bash
docker run -d --name runlight -p 3000:3000 -v runlight:/data ghcr.io/runlightsh/runlightQuando um proxy na mesma máquina adiciona HTTPS, como em Coloque na internet, publique a porta só no endereço de loopback, com -p 127.0.0.1:3000:3000. O Docker abre uma porta publicada passando por cima de firewalls como o ufw, e um cliente que chega direto à porta sem HTTPS pode informar qualquer host e enviar um endereço encaminhado falso.
Com Node 22 ou mais recente, rode isto no lugar.
bash
npx runlight.shO servidor escuta na porta 3000. Ele guarda os dados numa pasta chamada runlight-data no diretório de onde você o inicia, ou em /data dentro do Docker.
Crie sua conta
Na primeira inicialização, o servidor imprime no log um link de configuração com um código de uso único. Abra esse link e informe seu endereço de e-mail e uma senha de pelo menos dez caracteres, digitada duas vezes para que um erro de digitação não deixe você trancado do lado de fora. O link só funciona enquanto o servidor não tem nenhuma conta, então ninguém que encontre um servidor novo antes de você consegue tomá-lo.
No Docker, é no log que você deve olhar.
bash
docker logs runlightO link começa com http://localhost:3000. Quando o servidor roda em outro lugar, mantenha tudo a partir de /setup e coloque o endereço do próprio servidor na frente, como https://stats.example.com/setup?code=.... Cada inicialização gera um código novo, então depois de reiniciar use o link das linhas mais recentes do log.
Quem configura o servidor é o proprietário dele. O proprietário e os administradores convidam pessoas em Configurações, Pessoas, como administrador, membro ou leitor.
| Função | O que pode fazer |
|---|---|
| Proprietário | Tudo. Ninguém mais pode mudar a função do proprietário nem removê-lo. |
| Administrador | Tudo o que o proprietário pode, inclusive gerenciar pessoas, exceto mudar ou remover o proprietário. |
| Membro | Alterar as configurações de todos os sites, como metas, funis, links curtos, domínios de links, links de compartilhamento, relatórios por email e importações, e criar tokens de API. Membros não podem gerenciar pessoas, configurar o serviço de e-mail ou o assistente, nem excluir um site. |
| Leitor | Ver as estatísticas de todos os sites sem alterar nada. |
O proprietário pode passar a propriedade para um administrador com Tornar proprietário em Configurações, Pessoas, depois de digitar a própria senha, e passa a ser administrador. O convite sai por e-mail quando o servidor tem um serviço de e-mail (configurado em Configurações, Serviço de e-mail), e o painel sempre mostra o link também, para você poder enviá-lo de outro jeito. A pessoa abre o link, escolhe uma senha e já entra. Um link funciona uma vez, durante sete dias, e Enviar de novo gera um novo. Todo mundo pode mudar a própria senha depois em Conta, no rodapé do painel. Um servidor de antes dessas funções mantém o primeiro proprietário como proprietário, e os outros proprietários viram administradores. Remover alguém, ou transformar a pessoa em leitor, também apaga os tokens de API que ela criou e os apps que ela conectou, como o Claude ou um hub. Tokens criados com RUNLIGHT_TOKEN, ou antes desta versão, não têm autor registrado, então depois de remover alguém confira esses tokens em Configurações, API e IA.
Login em duas etapas
Qualquer pessoa pode ativar o login em duas etapas em Conta, no rodapé do painel. Confirme sua senha, escaneie o QR code com um app autenticador como 1Password, Google Authenticator ou Authy, e digite o código que ele mostra. A partir daí, o login pede um código novo depois da senha. Você também recebe dez códigos de recuperação, mostrados uma única vez, e cada um faz você entrar uma vez se o celular sumir. O proprietário ou um administrador pode redefinir as duas etapas de outra pessoa em Configurações, Pessoas, depois de digitar a própria senha, mas só o proprietário pode mudar as do proprietário. Ativar ou desativar o login em duas etapas encerra a sessão em todos os outros navegadores, e o navegador que você está usando continua com a sessão ativa.
Limites de login
Um endereço tem direito a dez senhas erradas para uma conta a cada quinze minutos, e a conta aceita cinquenta vindas de qualquer lugar. Cada tentativa é contada assim que chega, então uma rajada de palpites enviados de uma vez não vai mais longe. Quando a conta está no limite, um navegador que já entrou nela antes continua entrando, e todas as outras tentativas recebem a mesma resposta, esteja a senha certa ou não. Com o login em duas etapas ativado, essa resposta é a etapa do código, onde só o ticket de uma senha certa passa, então você ainda entra a partir de um navegador novo. Sem ele, uma senha certa envia para você por e-mail um link para entrar, quando o servidor tem um serviço de e-mail, e caso contrário a conta espera quinze minutos. O link funciona uma vez, durante quinze minutos, e usá-lo cancela qualquer link enviado antes dele. A etapa do código aceita cinco códigos errados a cada quinze minutos, e confirmar uma nova configuração de duas etapas aceita cinco antes de precisar começar de novo. As contagens ficam na memória, com endereços e endereços de e-mail transformados em hash por uma chave criada a cada inicialização.
Senhas esquecidas
Se alguém ficar trancado do lado de fora, rode o comando password no servidor para dar uma nova senha à conta, que ele imprime. Ele também desativa o login em duas etapas dessa conta, já que quem está no servidor é quem diz ser. O mesmo comando cria uma conta nova, que é a do proprietário num servidor ainda sem ninguém e a de um administrador nos outros casos.
bash
npx runlight.sh password someone@example.comNo Docker, rode o mesmo comando dentro do contêiner.
bash
docker exec runlight node node_modules/runlight.sh/dist/cli.js password someone@example.comAdicione seus sites
Depois que você entra, o painel pede o domínio do seu primeiro site. A tela seguinte mostra a tag do script para as páginas desse site, já com o endereço do servidor e o id do site preenchidos.
html
<script defer src="https://stats.example.com/s.js?site=example.com" data-site="example.com"></script>Adicione mais sites pelo menu ao lado do nome do site. Em Configurações, Geral, você pode mudar os domínios, o nome e o fuso horário de um site, ou excluir o site junto com tudo o que foi registrado para ele.
Conecte sites que contam por conta própria
Um site com o Runlight dentro do próprio app também pode entrar neste servidor, para que todos os sites fiquem num só painel. Escolha Adicionar um site, Conectar outro Runlight, e informe o endereço do Runlight do app, como https://example.com/runlight. Seu navegador abre o Runlight desse app, onde você entra se precisar, escolhe o site e clica em Allow. Você volta para cá com o site adicionado.
Os números do site continuam no banco de dados do próprio app. Este servidor os lê pela API do app toda vez que você olha, então eles estão sempre atualizados. As metas, os funis, os links curtos, os domínios de links, os relatórios por email, os links de compartilhamento e o tempo que o site guarda as visitas podem ser alterados daqui, e cada mudança é salva no app. Pessoas, tokens, importações e o serviço de e-mail do app ficam com o app. Todos os sites, no menu de sites, coloca todos os sites lado a lado para as datas que você escolher.
O app guarda a permissão como um token em Configurações, API e IA, limitado a esse único site. Excluí-lo ali desconecta este servidor na hora. Um site conectado com um token só de leitura antes disso existir mostra Permitir mudanças nas configurações, que segue os mesmos passos. Se o app excluir esse token, Ligar de novo nas configurações do site cria um novo, e desconectar um site aqui exclui o token dele lá.
Se o app roda um Runlight mais antigo que este, conecte-o com um token. Crie um em Configurações, API e IA do app e escolha Usar um token de API na hora de conectar. Um token de leitura mostra os números do site aqui, e as configurações dele continuam no app.
Coloque na internet
O servidor fala HTTP simples, então rode-o atrás de um proxy que adicione HTTPS. Com o Caddy, a configuração inteira para um servidor em stats.example.com é esta.
Caddyfile
stats.example.com {
reverse_proxy localhost:3000
}Defina RUNLIGHT_URL com o endereço público do servidor, como https://stats.example.com. Assim os links curtos nunca podem tomar esse nome, e os e-mails de convite e de relatório apontam para ele, seja qual for o cabeçalho Host de uma requisição. Um hub conectado só adiciona domínios de links e relatórios por email depois que ela estiver definida.
O Runlight lê o endereço de cada visitante na última entrada de X-Forwarded-For, a que o seu proxy adiciona. Defina TRUST_PROXY como x-real-ip ou cf-connecting-ip quando o endereço vier nesse cabeçalho, como atrás da Cloudflare e de outro proxy. Defina TRUST_PROXY=false quando não houver nada na frente do servidor, para que um visitante não consiga enviar um endereço falso.
Links curtos nos seus próprios domínios
Qualquer domínio apontado para o servidor pode servir links curtos na raiz, sem mais nada para instalar. Aponte o domínio para o servidor com um registro CNAME, faça seu proxy aceitá-lo com HTTPS e depois adicione-o em Configurações, Domínios personalizados. No Caddy, isso significa listar o domínio ao lado do domínio do próprio servidor.
Caddyfile
stats.example.com, go.example.com {
reverse_proxy localhost:3000
}Todo link também responde em /go/your-slug no domínio do próprio servidor. As páginas do próprio servidor, como /login e tudo em /api, também respondem como o servidor num domínio de links, então um link com um desses slugs só funciona em /go/. Um domínio de links nunca pode ser o endereço público do servidor nem um nome a partir do qual o proprietário ou um administrador já entrou, e se um foi adicionado assim antes, entrar em /login ainda abre o painel para você poder removê-lo. O servidor lembra os primeiros 20 nomes a partir dos quais eles entram, então defina RUNLIGHT_URL se ele responder em mais nomes que isso.
Localizações
Atrás da Cloudflare, o Runlight pega o país, a região e a cidade de cada visitante nos cabeçalhos que a Cloudflare adiciona. Sem eles, o servidor baixa o banco de dados gratuito de cidades do DB-IP para a pasta de dados na primeira inicialização e busca a nova versão de cada mês. O arquivo tem cerca de 130 MB e o servidor o mantém na memória. A licença do DB-IP pede crédito, então o rodapé do painel cita o nome dele.
Defina RUNLIGHT_GEO=country para usar o banco de dados de países do DB-IP, que é menor, tem cerca de 8 MB e não traz regiões nem cidades. Defina como off para não consultar nada, ou como o caminho de um arquivo MMDB seu, como o GeoLite2 City da MaxMind.
Configurações
O servidor lê as configurações em variáveis de ambiente.
| Variável | O que faz |
|---|---|
PORT |
A porta em que escutar. O padrão é 3000. |
HOST |
O endereço em que escutar. O padrão é 0.0.0.0. |
DATA_DIR |
A pasta do arquivo SQLite, do segredo e dos dados de localização. O padrão é ./runlight-data, ou /data no Docker. |
DATABASE_URL |
Um endereço postgres:// guarda os dados no Postgres em vez do SQLite, e um endereço mysql:// ou mariadb:// os guarda no MySQL ou no MariaDB. |
RUNLIGHT_SECRET |
A chave que assina os logins e criptografa as chaves salvas, do e-mail, do Assistente de IA, das instalações conectadas e do login em duas etapas. Sem ela, o servidor cria uma e a guarda em DATA_DIR. |
RUNLIGHT_URL |
O endereço público do servidor, como https://stats.example.com, que nunca pode virar um domínio de links. Os e-mails de convite e de relatório apontam para ele. |
RUNLIGHT_TOKEN |
Um token que scripts podem enviar como bearer, além dos tokens de API criados no painel. |
RUNLIGHT_OBSERVE_KEY |
Uma única chave que um site WordPress, Drupal ou Craft pode usar para informar agentes de IA, de qualquer site. Cada site também tem a própria chave de agentes, mostrada em Configurações, Instalação e limitada a esse site, que é a melhor escolha. |
TRUST_PROXY |
Defina como false quando não houver proxy na frente do servidor. |
RUNLIGHT_GEO |
De onde vêm as localizações quando nenhum cabeçalho as informa. É city por padrão, e pode ser country, off ou o caminho de um arquivo MMDB. |
Relatórios por email e a verificação agendada
O servidor roda sozinho a verificação agendada do Runlight a cada cinco minutos, então não precisa de cron. Configure um serviço de e-mail em Configurações, Serviço de e-mail, adicione quem recebe relatórios em Configurações, Relatórios por email, e os relatórios saem por conta própria.
Backups e atualizações
Faça backup da pasta de dados. Ela contém o arquivo SQLite e o arquivo secret, e sem o segredo as chaves salvas não podem ser lidas e todo mundo precisa entrar de novo. Essas chaves são as do serviço de e-mail, a do Assistente de IA, os tokens das instalações conectadas e os segredos de duas etapas de todo mundo, então o login em duas etapas também precisa ser configurado de novo. Para atualizar, baixe a nova imagem ou rode npx runlight.sh@latest, e o banco de dados se atualiza sozinho na inicialização.
Mais de uma cópia
Várias cópias do servidor podem compartilhar um único banco de dados Postgres, MySQL ou MariaDB, por exemplo atrás de um balanceador de carga. Cada cópia relê a lista de sites e de instalações conectadas a cada cinco minutos, então um site adicionado em qualquer cópia aparece nas outras em até cinco minutos. Todo o resto, das visitas às metas e aos links, é compartilhado na hora.
Agentes de IA a partir de um log
Agentes de IA como GPTBot e ClaudeBot leem páginas sem rodar JavaScript, então a tag do script nunca os vê. Num site com o Runlight dentro do app, ou com um plugin para WordPress, Drupal ou Craft, eles são contados onde a página é servida. Para qualquer outro site que você hospeda, o log de acesso do servidor web os registra, e o comando agents lê esse log.
bash
npx runlight.sh agents --log /var/log/nginx/access.log --to https://stats.example.com --key rlo_... --site https://example.com --followA chave é a chave de agentes do site, mostrada no Runlight em Configurações, Instalação, e ela só pode informar leituras desse site. --site é o endereço do site, para logs no formato padrão do nginx ou do Apache, que deixam o host de fora. Os logs em JSON do Caddy trazem o host, então ali ele não é necessário.
Com --follow, o comando continua rodando, envia as leituras conforme acontecem e segue em frente quando o log é rotacionado, terminando o arquivo antigo antes de passar para o novo. Um serviço do systemd ou um gerenciador de processos o mantém rodando. Adicione --state ./agents.json para que uma reinicialização continue de onde parou. Sem --follow, ele lê o log uma vez e para, e com --state a próxima execução começa onde a última terminou, o que combina com cron. Só uma execução por vez pode usar um arquivo de estado. Ela mantém uma trava ao lado do arquivo (agents.json.lock), então uma segunda execução, como um job de cron que começa enquanto o anterior ainda está enviando, para com uma mensagem e não envia nada duas vezes. Uma trava deixada por uma execução que caiu é assumida pela próxima.
Só as leituras de página bem-sucedidas de agentes de IA conhecidos saem da máquina, cada uma com o endereço da página, o user agent do agente e o horário em que foi servida. Os endereços dos visitantes e todo o resto do log ficam onde estão.