SSD Nodes Learn 🎉 VPS desde $5.50/mês
Guias Matt ConnorPor Matt Connor · Atualizado 2026-08-16

Analytics self-hosted: opções para um VPS pequeno

Compare Plausible, Umami, Matomo, GoatCounter e GoAccess: veja RAM, banco, crescimento do disco, proxy reverso e o impacto dos bloqueadores.

Qual ferramenta de análise web self-hosted deve executar num VPS?

A análise web self-hosted divide-se em duas famílias, e escolher a família errada custa mais do que escolher o produto errado. Uma família executa um pequeno script no navegador do visitante e armazena os dados comunicados por esse script. A outra família lê o access log que o seu servidor web já escreve. Tudo o resto, incluindo a base de dados e a memória necessária, resulta dessa escolha.

A resposta curta para um servidor pequeno. GoatCounter e Medama cabem em 1 GB, porque cada um é um processo que trabalha sobre um único ficheiro. Umami adiciona um contentor Postgres e fornece um dashboard que uma pessoa sem conhecimentos técnicos consegue ler. Plausible Community Edition e Rybbit executam ambos o ClickHouse, por isso planeie 2 GB de RAM ou mais. Matomo é o produto completo e requer um servidor dimensionado para o seu tráfego. GoAccess não adiciona nada à página, porque lê um log que já existe.

Tag de script ou log do servidor: o que cada um consegue ver

Uma tag de script mede os browsers. A página é carregada, o script é executado e envia um pedido ao seu coletor. Tudo o que interromper essa sequência fica invisível para si: JavaScript desativado, uma lista de filtros que bloqueia o pedido, uma falha no pedido ao coletor ou um crawler que nunca executa scripts.

Um analisador de logs mede pedidos. O servidor Web escreve uma linha por pedido, quer instale alguma coisa quer não, por isso os dados já estão no disco. Ele vê todos os crawlers e todos os acessos a um ficheiro que não contenha uma tag de script. Não consegue ver o que aconteceu dentro do browser. Também não consegue ver uma página servida a partir da cache do browser ou de uma CDN (content delivery network) à frente do seu servidor, porque esse pedido nunca chegou ao servidor.

Os dois números não vão coincidir, e nenhum deles está necessariamente errado. O Matomo consegue fazer as duas coisas e documenta o que a importação de logs deixa de fornecer em comparação com o seu tracker JavaScript: resolução do ecrã e títulos das páginas, eventos, acompanhamento de conteúdo, mapas de calor, gravações de sessões e análise de formulários. Essa é a limitação de contar pedidos em vez de browsers.

O tráfego de bots é a outra metade da diferença. As contagens baseadas em logs incluem crawlers, a menos que os filtre. Num site comum, a proporção de crawlers é suficientemente grande para alterar as conclusões. O GoAccess e a importação de logs do Matomo filtram ambos os bots conhecidos. Nenhum consegue filtrar um crawler que falsifique o seu user agent. Por isso, é uma boa prática combinar qualquer contagem baseada em logs com bloquear crawlers de IA no servidor e ler o log depois do bloqueio, não antes.

GoAccess: analytics a partir do log que já tem

Instale-o a partir do repositório próprio do projeto para Debian e Ubuntu, porque os pacotes das distribuições ficam atrasados em relação às versões lançadas.

wget -O - https://deb.goaccess.io/gnugpg.key | gpg --dearmor | sudo tee /usr/share/keyrings/goaccess.gpg >/dev/null
echo "deb [signed-by=/usr/share/keyrings/goaccess.gpg arch=$(dpkg --print-architecture)] https://deb.goaccess.io/ $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/goaccess.list
sudo apt-get update
sudo apt-get install goaccess

Depois, aponte-o para o log e escreva um relatório estático.

goaccess /var/log/nginx/access.log -o ~/report.html --log-format=COMBINED

Esse comando falha com Permission denied para um utilizador normal, porque no Ubuntu o log do nginx pertence a root e ao grupo adm. Adicione-se a esse grupo com sudo usermod -aG adm $USER e, em seguida, termine a sessão e inicie-a novamente, porque a associação a grupos é lida no início da sessão. Execute id e confirme que adm aparece na lista antes de tentar novamente.

Um relatório sobre o log ativo abrange apenas o conteúdo que o logrotate ainda não moveu. Os pedidos de ontem estão em access.log.1 e os mais antigos estão comprimidos, por isso uma vista semanal também tem de ler os ficheiros rodados.

zcat /var/log/nginx/access.log.*.gz | goaccess - --log-format=COMBINED -o ~/last-week.html

Também existe um modo ativo, --real-time-html, que atualiza a página através de um WebSocket. Isto requer uma segunda porta e a sua própria regra de proxy. Para a maioria dos sites, um relatório horário escrito pelo cron é suficiente e há menos elementos para proteger.

GoatCounter: um binário Go e um ficheiro SQLite

GoatCounter é distribuído como um binário compilado estaticamente, por isso não é necessário instalar um runtime. Transfira uma compilação da página de versões e execute-a, ou use a imagem.

docker run -p 8080:8080 -v goatcounter-data:/home/goatcounter/goatcounter-data arp242/goatcounter

Quando é executado como binário, goatcounter serve fica à escuta na porta 8080 e cria a base de dados SQLite em ./goatcounter-data/db.sqlite3. Crie o primeiro site a partir da linha de comandos, em vez de usar o assistente Web, quando a instância já estiver atrás de um proxy.

goatcounter db create site -vhost=stats.example.com -user.email=me@example.com

Pode gerir o seu próprio certificado com goatcounter serve -listen=:443 -tls=tls,rdr,acme, usando ACME (ambiente de gestão automática de certificados). Isto é útil num servidor que não execute mais nenhum serviço. Quando nginx ou Caddy já controla a porta 443, mantenha o GoatCounter na porta 8080 e faça proxy para ele. O script de tracking tem cerca de 3.5K, segundo o próprio projeto, e existe um pixel de tracking para páginas sem JavaScript. Se o SQLite se tornar o limite num site com muita utilização, o mesmo binário aceita Postgres com goatcounter serve -db 'postgresql+dbname=goatcounter'. As cópias de segurança consistem em copiar um ficheiro, que é o principal argumento a favor deste tipo de ferramenta.

Medama: um único contentor que declara 256 MB

Medama é a opção de binário único mais recente desta lista. Por conceção, não utiliza cookies, e o projeto declara um tracker com menos de 1 KB, além de sites pequenos executados em máquinas virtuais com 256 MB de memória. Estas são as afirmações publicadas pelo projeto, não valores medidos para este guia.

docker volume create medama-data
docker run -d -p 127.0.0.1:8080:8080 -v medama-data:/app/data ghcr.io/medama-io/medama:latest

O comando oficial publica a porta como 8080:8080. O prefixo de loopback acima é deliberado, e a secção sobre reverse proxy explica o motivo. O primeiro início de sessão é feito com admin e a palavra-passe é CHANGE_ME_ON_FIRST_LOGIN; o nome dessa palavra-passe corresponde à instrução.

Existe um modo de falha documentado que pode causar problemas. O início de sessão só funciona através de HTTPS ou em localhost. Por isso, se configurar o proxy antes do certificado, o formulário rejeita uma palavra-passe correta e não apresenta o motivo. Conclua primeiro a configuração de TLS (transport layer security) e só depois inicie sessão.

Umami: PostgreSQL e um dashboard conhecido

git clone https://github.com/umami-software/umami.git
cd umami
docker compose up -d

Isso inicia a aplicação na porta 3000 com um contentor PostgreSQL ao lado. A documentação indica PostgreSQL v12.14 como versão mínima e Node.js 18.18 ou mais recente se fizer a compilação a partir do código-fonte. Existe uma imagem pré-compilada, docker.umami.is/umami-software/umami:postgresql-latest, que precisa de DATABASE_URL apontar para uma base de dados que já esteja em execução.

O primeiro início de sessão é admin com a palavra-passe umami. Altere-a antes de apontar o DNS para o servidor, porque a instância fica acessível a partir da internet assim que o registo for resolvido e o proxy responder. Para obter os detalhes do Compose, dos ficheiros de ambiente e da política de reinício, consulte uma stack Docker Compose num VPS em vez de copiar uma stack que não leu.

A ocupação de recursos consiste num processo Node e no Postgres. É mais pesada do que a de um binário único e muito mais leve do que a de qualquer aplicação que execute o ClickHouse.

Plausible Community Edition: o ClickHouse define o mínimo de RAM

git clone -b v3.2.1 --single-branch https://github.com/plausible/community-edition plausible-ce
cd plausible-ce
touch .env
echo "BASE_URL=https://stats.example.com" >> .env
echo "SECRET_KEY_BASE=$(openssl rand -base64 48)" >> .env
docker compose up -d

A versão v3.2.1 é a atual em agosto de 2026, e o comando de clone fixa essa versão de propósito. A stack tem três componentes: a aplicação, o Postgres para contas e definições, e o ClickHouse para os dados dos eventos. SECRET_KEY_BASE tem de ser pelo menos uma string de 64 bytes, que é o que a chamada openssl produz.

Os requisitos do próprio Plausible pedem pelo menos 2 GB de RAM para que o ClickHouse e a aplicação não sejam terminados pelo OOM killer, além de uma CPU com suporte a SSE 4.2 ou NEON, necessário para o ClickHouse. Vale a pena verificar este segundo requisito antes da compra. Essa é uma das diferenças práticas ao escolher entre um VPS ARM e um VPS x86. O ClickHouse também usa toda a memória que considerar disponível. Por isso, num servidor partilhado, defina um limite conforme descrito em limitar a memória dos contentores no Compose.

BASE_URL tem de ser exatamente igual ao URL público. Caso contrário, inicia sessão, a aplicação redireciona para o host errado e o cookie de sessão é gravado para um domínio que não corresponde ao domínio aberto no navegador. Assim, volta ao formulário de início de sessão sem qualquer mensagem de erro.

O ficheiro compose fornecido não publica nenhuma porta, porque se pressupõe a existência de um proxy à frente da aplicação. Adicione uma substituição que publique a porta predefinida da aplicação apenas na interface de loopback.

cat > compose.override.yml << EOF
services:
    plausible:
        ports:
            - 127.0.0.1:8000:8000
EOF

Matomo: o produto completo e o servidor de que precisa

O Matomo funciona com PHP e MySQL ou MariaDB, por isso integra-se na pilha Web clássica, e não numa pilha de contentores. É também a única ferramenta aqui que publica requisitos de hardware de acordo com o volume de tráfego.

ChartMatomo sizing guidance by monthly pageviews
The data behind this chart
[
  {
    "label": "100K/month",
    "cpu_cores": 2,
    "ram_gb": 2,
    "disk_gb": 50
  },
  {
    "label": "1M/month",
    "cpu_cores": 4,
    "ram_gb": 8,
    "disk_gb": 250
  },
  {
    "label": "10M/month",
    "cpu_cores": 8,
    "ram_gb": 16,
    "disk_gb": 400
  }
]

Estes são os requisitos mínimos publicados pelo Matomo em agosto de 2026, e não medições feitas para este guia. Até 100,000 visualizações de página por mês, são necessários 2 núcleos de CPU, 2 GB de RAM e 50 GB de SSD. Um único servidor aloja a aplicação e a base de dados. Em 1M/month, são necessários 8 GB de RAM e 250 GB de disco. Em 10M/month, o Matomo recomenda dois servidores, e a última linha mostra o servidor da base de dados: 16 GB de RAM e 400 GB de disco. Compare estes valores de disco com as opções baseadas num único binário, em que todo o conjunto de dados é um ficheiro SQLite.

O arquivamento é o que mais surpreende. Por predefinição, o Matomo gera os relatórios quando alguém abre o dashboard. À medida que os dados aumentam, o dashboard fica mais lento e acaba por exceder o tempo limite. A correção documentada consiste em desativar o arquivamento acionado pelo browser nas definições gerais e executar o arquivador através do cron, com o utilizador proprietário dos ficheiros do Matomo, a partir do diretório do Matomo.

php console core:archive --url=https://analytics.example.com

O Matomo também mantém tabelas de logs brutos junto das tabelas de relatórios processados. Pode eliminar dados brutos antigos e relatórios antigos segundo um calendário. Ative essa opção durante a instalação, e não apenas quando o disco estiver cheio. O Matomo também pode importar logs de acesso do servidor, o que faz dele o único produto aqui que abrange as duas famílias ao mesmo tempo.

Rybbit e as stacks mais recentes

git clone https://github.com/rybbit-io/rybbit.git
cd rybbit
chmod +x *.sh
./setup.sh your.domain.name

O Rybbit é uma opção recente, com um dashboard moderno. O script de configuração grava o ficheiro de ambiente e inicia a stack com Docker Compose. Executa o ClickHouse e inclui o Caddy como servidor web próprio. O Caddy ocupa a porta 443 e solicita um certificado para o domínio indicado. Num servidor onde o nginx já utiliza a porta 443, o script não conseguirá associar-se à porta. Nesse caso, utilize o método manual com Compose do projeto e coloque-o atrás do proxy existente. A documentação indica pelo menos 2 GB de RAM, testes no Ubuntu 24 LTS e ARMv8.2-A ou posterior em sistemas ARM, devido ao ClickHouse.

A ressalva aplicável a qualquer projeto recente é simples: as funcionalidades são adicionadas rapidamente, mas as alterações incompatíveis também surgem com rapidez. Fixe uma tag, leia as notas da versão antes de executar pull e faça primeiro um backup da base de dados.

Retenção e crescimento do disco: meça no seu próprio servidor

O crescimento do disco depende do que a ferramenta armazena por evento. O GoatCounter agrega os acessos em contadores, por isso o ficheiro cresce mais com o número de páginas distintas e de dias do que com o volume bruto. O Umami e o Matomo armazenam linhas por evento, e o Matomo armazena também tabelas de relatórios processados além das tabelas brutas. O ClickHouse armazena os eventos em colunas e comprime-os fortemente. É por isso que o Plausible suporta um volume que poderia sobrecarregar um armazenamento baseado em linhas.

Este guia não apresenta um valor em megabytes por milhão de visualizações de página, porque esse valor não foi medido no seu tráfego. Faça a medição. Ajuste os nomes do serviço e do utilizador para corresponderem ao seu próprio ficheiro Compose.

du -h goatcounter-data/db.sqlite3
docker compose exec db psql -U umami -d umami -c "SELECT pg_size_pretty(pg_database_size('umami'));"
docker compose exec plausible_events_db clickhouse-client -q "SELECT formatReadableSize(sum(bytes_on_disk)) FROM system.parts WHERE active"

Registe o número, aguarde uma semana, registe-o novamente e divida a diferença pelo número de visualizações de página apresentado pelo dashboard para essa semana. Esse valor corresponde ao seu site e à filtragem de bots que utiliza, por isso é mais útil do que qualquer média publicada. Depois, defina um limite de retenção enquanto o número ainda é pequeno. Um disco cheio interrompe todos os serviços no VPS, não apenas o serviço de análise, o que constitui o argumento mais forte para manter o volume da base de dados num local que o df -h irá monitorizar. Esse risco merece mais atenção num servidor que já armazena algo volumoso, porque um servidor de fotografias autoalojado irá esgotar o disco muito antes de qualquer base de dados de análise se aproximar desse limite.

Como funciona atrás de um reverse proxy num subdomínio

Coloque o collector num subdomínio do site que mede, como stats.example.com. Assim, o pedido ao collector é feito como first-party e não é afetado pelas regras do navegador que bloqueiam pedidos third-party.

Associe a aplicação ao loopback quando publicar a porta do container. O Docker escreve as suas próprias regras de firewall antes do ufw. Por isso, um container publicado como -p 3000:3000 fica acessível a partir da Internet, mesmo quando ufw status indica que a porta está bloqueada. Teste a partir de outra máquina com curl http://SERVER_IP:3000 para obter o dashboard. Publicado como -p 127.0.0.1:3000:3000, o mesmo teste devolve Connection refused e apenas o proxy consegue aceder-lhe.

server {
    listen 443 ssl;
    server_name stats.example.com;

    location / {
        proxy_pass http://127.0.0.1:3000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

Os cabeçalhos de encaminhamento são obrigatórios neste caso. Sem X-Forwarded-For, todas as visitas chegam de 127.0.0.1. O relatório por país fica vazio e o número de visitantes únicos aproxima-se de um. Cada projeto define qual cabeçalho aceita e em que configuração. Consulte a documentação do proxy do projeto uma vez, em vez de presumir. O Caddy define estes cabeçalhos automaticamente. Um Caddyfile para a mesma tarefa tem duas linhas.

stats.example.com {
    reverse_proxy 127.0.0.1:3000
}

Se ainda não escolheu um proxy, a comparação entre nginx, Caddy e Traefik explica qual é mais adequado para um único servidor com alguns subdomínios.

Ainda precisa de um banner de cookies se alojar tudo no seu próprio servidor?

O alojamento próprio muda quem detém os dados. Não muda o que a lei diz sobre esses dados. Separe duas regras. A regra de consentimento da ePrivacy aplica-se ao armazenamento ou à leitura de qualquer conteúdo no dispositivo do visitante. Por isso, uma ferramenta que não define cookies nem grava dados no armazenamento local fica fora desse requisito específico. O GDPR aplica-se ao tratamento de dados pessoais. Um endereço IP conta como dado pessoal. Por isso, continua a precisar de uma base legal, de um prazo de retenção e de uma resposta quando alguém perguntar que dados mantém sobre essa pessoa.

Plausible, Umami, GoatCounter e Medama não definem cookies por predefinição. O que cada ferramenta calcula a partir dos dados varia entre projetos e versões. Consulte a documentação de privacidade do próprio projeto em vez de se basear num resumo. O Matomo inclui anonimização de IP e um endpoint de opt-out que pode ativar na interface de administração.

Os reguladores chegam a conclusões diferentes em países diferentes. A CNIL de França, por exemplo, publica as condições em que a medição de audiência pode ficar isenta de consentimento. Esta secção é um resumo factual e não constitui aconselhamento jurídico. Para um site real com utilizadores reais, consulte um advogado na sua jurisdição.

Há um ponto que muitas pessoas ignoram: um log de acesso também é dado pessoal. O GoAccess não adiciona nenhum script à página e, ainda assim, trata endereços IP. Por isso, a análise baseada em logs não fica automaticamente fora das regras.

Bloqueadores de anúncios e por que os seus números vão diminuir

As listas de filtros fazem correspondência com o hostname e com padrões de URL. Um produto de analytics alojado é fácil de identificar, porque todos os utilizadores o carregam a partir do mesmo hostname conhecido. Mover o collector para o seu próprio subdomínio remove esse hostname do pedido. Servir o script a partir de um caminho escolhido por si remove o nome de ficheiro conhecido. Ambas as alterações mudam aquilo com que uma lista tem de fazer correspondência.

Este texto não afirma uma taxa de bloqueio, porque não mediu nenhuma. A percentagem de visitantes que bloqueia uma determinada configuração depende do seu público. Um público de developers bloqueia muito mais do que um público geral. Em vez disso, meça a sua própria diferença. Durante a mesma semana, conte os pedidos de páginas HTML no access log com GoAccess e compare esse valor com as pageviews comunicadas pela ferramenta baseada no seu script. No seu site, a diferença corresponde às visitas bloqueadas e às páginas servidas a partir da cache.

Espere que os totais mudem no dia em que deixar de usar um produto alojado. Espere também que parte dessa alteração não tenha qualquer relação com bloqueios. Os produtos não usam todos a mesma definição de pageview, não tratam da mesma forma uma mudança de rota dentro de uma single-page application e não terminam uma sessão no mesmo momento. Compare as tendências ao longo de várias semanas antes de concluir que o tráfego diminuiu.

Qual escolher para cada site

  • Um site pessoal ou blog com cerca de 50,000 visualizações de página por mês: GoatCounter ou Medama, num VPS de 1 GB, com cópias de segurança feitas através de uma cópia de ficheiros.
  • Um site onde não pode adicionar um script, ou com uma audiência que o bloqueia frequentemente: GoAccess sobre o log existente, executado segundo um agendamento.
  • Um site de uma pequena empresa cujo dashboard é consultado por outra pessoa: Umami, com o seu container Postgres.
  • Um site onde pretende definir objetivos e funis, num servidor com 2 GB de RAM ou mais: Plausible Community Edition, ou Rybbit se quiser o dashboard mais recente e aceitar um projeto mais novo.
  • Muitos sites, muitas contas de utilizador ou a necessidade de manter dados brutos segundo a sua própria política de retenção: Matomo, dimensionado com base nas orientações publicadas acima.

Comece pela ferramenta mais pequena que responda à sua pergunta concreta. Migrar de GoatCounter para Plausible mais tarde custa-lhe um subdomínio e parte do histórico. Migrar de Matomo para outra solução implica uma migração que provavelmente não será agradável. Se ainda estiver a decidir o que deve ficar no mesmo servidor, o guia mais abrangente de self-hosting explica o que pode ser instalado a seguir. Se o que realmente pretende é rastreio ao nível dos pedidos de uma aplicação, em vez de contagens de visitantes, um serviço de observabilidade self-hosted é a ferramenta adequada para esse trabalho.

FAQ

As análises autogeridas eliminam a necessidade de um banner de cookies?

Não, e são duas questões distintas. A regra de consentimento da ePrivacy abrange o armazenamento ou a leitura de algo no dispositivo do visitante. Por isso, uma ferramenta que não define cookies nem grava dados no armazenamento local fica fora desse requisito específico. O GDPR é uma regra diferente e abrange o tratamento de dados pessoais. Um endereço IP é um dado pessoal, pelo que continua a precisar de uma base legal e de um limite de retenção, mesmo sem cookies. O alojamento no seu próprio servidor transfere os dados para a sua infraestrutura e torna-o a entidade responsável por eles. Consulte as orientações do seu regulador e peça aconselhamento jurídico para o seu caso.

De quanta RAM precisa uma ferramenta de análise autogerida num VPS?

É o datastore que determina esse requisito, não o dashboard. GoatCounter e Medama são executados como um único processo sobre um único ficheiro, e a documentação do Medama indica que sites pequenos funcionam em máquinas com 256 MB. O Umami adiciona um contentor Postgres junto de uma aplicação Node. A Plausible Community Edition e o Rybbit usam ambos ClickHouse, e os dois projetos indicam um mínimo de 2 GB. As orientações do próprio Matomo começam em 2 núcleos de CPU e 2 GB de RAM para até 100,000 visualizações de páginas por mês.

Por que razão os meus números autogeridos são inferiores aos da ferramenta de análise que substituí?

Há duas causas, e ambas são reais. As listas de filtros bloqueiam alguns pedidos ao coletor, pelo que todas as ferramentas baseadas em scripts perdem essas visitas. Os produtos também fazem a contagem de forma diferente, porque a definição de visualização de página e o momento em que uma sessão termina variam entre ferramentas. Compare uma semana de pedidos de páginas HTML no access log com a mesma semana de visualizações de páginas baseadas em scripts. Essa diferença corresponde às visitas bloqueadas e às páginas servidas a partir de cache, medida no seu próprio site em vez de ser obtida a partir de uma taxa publicada por terceiros.

Posso executar Plausible ou Rybbit num VPS ARM?

Ambos usam ClickHouse, e o ClickHouse precisa de SSE 4.2 em x86 ou de NEON em ARM. Os requisitos da Plausible indicam exatamente isso, e a documentação do Rybbit diz que os sistemas ARM precisam de ARMv8.2-A ou mais recente. Os núcleos de servidores ARM atuais cumprem esse requisito, mas os mais antigos não. A falha manifesta-se quando o ClickHouse se recusa a iniciar com um erro relacionado com o conjunto de instruções, e não como um erro no log da aplicação. Num equipamento ARM pequeno, as ferramentas baseadas num único ficheiro evitam esta questão, porque nenhuma delas executa ClickHouse.

Devo analisar os logs do servidor em vez de usar um script de monitorização?

Use a análise de logs quando não puder adicionar um script, quando o seu público bloquear scripts com frequência ou quando quiser uma contagem que inclua crawlers. O GoAccess lê um log que o servidor já escreve, pelo que não adiciona peso às páginas nem uma base de dados. Em contrapartida, perde tudo o que acontece dentro do browser e não contabiliza páginas servidas por uma CDN ou pela cache do browser, porque esse pedido nunca chegou ao servidor. Muitos sites usam ambos e tratam-nos como duas medições diferentes.