Tutoriais de VPS
Umami auto-hospedado em VPS para análise de sites (2026): Docker Compose, PostgreSQL, HTTPS com Caddy e configuração anti bloqueadores de anúncios
Este tutorial explica como auto-hospedar o Umami em um VPS e montar um sistema de análise de visitas leve e amigável à privacidade. O conteúdo cobre a escolha entre Umami e Plausible, configuração do VPS, Docker Compose, PostgreSQL, HTTPS com Caddy, script de rastreamento, medidas anti bloqueadores de anúncios, backup, atualização, reforço de segurança e solução de problemas comuns.

Umami auto-hospedado em VPS para análise de sites (2026): Docker Compose, PostgreSQL, HTTPS com Caddy e configuração anti bloqueadores de anúncios
Muitos administradores de sites começam usando o Google Analytics diretamente. Ele é gratuito, poderoso e tem muita documentação, mas tem alguns problemas inevitáveis: carrega devagar, é bloqueado por bloqueadores de anúncios, gera pressão de conformidade com privacidade e os dados sempre ficam com outra pessoa.
Se você só quer saber quantas visitas o site recebe por dia, de onde vêm os visitantes e quais páginas são mais populares, na verdade não precisa de uma plataforma de análise muito pesada. O Umami é mais uma ferramenta leve de análise de sites auto-hospedada: a interface é limpa, não depende de cookies, respeita a privacidade por padrão e roda em um VPS pequeno.
Este artigo trata de como implantar o Umami em um VPS. Vamos usar Docker Compose para rodar o Umami e o PostgreSQL, e depois o Caddy para obter HTTPS automaticamente. Mais adiante também vamos falar sobre o script de rastreamento, medidas anti bloqueadores de anúncios, backup, atualização e problemas comuns.
Entre as opções comuns de análise de sites auto-hospedada estão Umami, Plausible, Matomo e outros.
O Matomo é muito completo em recursos, mas relativamente mais pesado, mais parecido com uma plataforma de análise completa. A experiência do Plausible é muito boa, mas a Community Edition auto-hospedada exige PostgreSQL mais ClickHouse, o que significa maior consumo de recursos e backup mais complexo.
As vantagens do Umami são diretas:
- Implantação simples; o contêiner da aplicação mais o PostgreSQL já bastam.
- Amigável para VPS pequenos; 1 GB de memória consegue rodar um site leve.
- Painel limpo; não é preciso aprender relatórios complexos.
- Suporta análise de vários sites, adequado para administradores individuais e equipes pequenas.
- Você pode personalizar o nome do script de rastreamento para reduzir a chance de ser detectado por bloqueadores de anúncios.
- Os dados ficam no seu próprio banco de dados, então backup e migração ficam sob seu controle.
Se o seu site já tem muito tráfego, ou depende fortemente de desempenho de consulta no nível do ClickHouse, o Plausible também vale a pena considerar. Mas para a maioria dos usuários de VPS, o Umami é mais adequado para auto-hospedagem leve, especialmente em máquinas pequenas com orçamento limitado.
O Umami não é pesado; o que realmente cresce são os dados de visitas no PostgreSQL.
| Cenário | Configuração recomendada |
|---|---|
| Blog pessoal, site de ferramentas, site institucional de baixo tráfego | 1 vCPU / 1 GB RAM / 20 GB SSD |
| Vários sites, de milhares a dezenas de milhares de PV por dia | 2 vCPU / 2 GB RAM / 40 GB SSD |
| Uso em equipe, retenção de longo prazo de grandes volumes de dados históricos | 2-4 vCPU / 4 GB RAM / 80 GB+ SSD |
Se você já tem um VPS rodando Caddy, Nginx, Uptime Kuma, Vaultwarden ou NocoDB, o Umami pode rodar junto como serviço adicional. Mas se essa máquina tiver apenas 512 MB de memória, tenha cuidado: PostgreSQL mais outros serviços podem atrair o OOM killer.
Este artigo assume que você já tem:
- Ubuntu 22.04 / 24.04 ou Debian 12.
- Docker e Docker Compose V2.
- Um domínio, por exemplo
analytics.example.com. - O registro A do domínio já aponta para o IP público do VPS.
- As portas 80 e 443 abertas para o Caddy obter HTTPS.
Verifique o Docker:
docker version
docker compose version
Se o Docker ainda não estiver instalado, instale primeiro antes de continuar. Este artigo foca no próprio Umami e não repete o básico de Docker.
Crie o diretório:
sudo mkdir -p /opt/umami
sudo chown -R "$USER":"$USER" /opt/umami
cd /opt/umami
mkdir -p backups caddy-data caddy-config
Gere dois segredos aleatórios:
openssl rand -hex 32
openssl rand -base64 32
O primeiro é usado como APP_SECRET, o segundo como senha do PostgreSQL. APP_SECRET deve permanecer inalterado a longo prazo; reinicializações, atualizações e migrações posteriores devem continuar usando o mesmo valor; não o regenere a cada implantação.
Crie .env:
nano .env
Escreva o conteúdo abaixo, substituindo o domínio e as senhas pelos seus:
UMAMI_DOMAIN=analytics.example.com
POSTGRES_PASSWORD=replace_with_a_long_database_password
APP_SECRET=replace_with_openssl_rand_hex_32
TRACKER_SCRIPT_NAME=metrics.js
COLLECT_API_ENDPOINT=/api/web-events
Explicando algumas variáveis:
UMAMI_DOMAIN: o domínio usado pelo proxy reverso do Caddy.POSTGRES_PASSWORD: a senha do banco de dados PostgreSQL.APP_SECRET: uma string aleatória que o Umami usa para proteger tokens de autenticação; cada instância deve ser diferente, e não a altere sem necessidade depois de entrar em produção.TRACKER_SCRIPT_NAME: altera o script de rastreamento padrão para um nome personalizado, reduzindo a chance de ser detectado por bloqueadores de anúncios.COLLECT_API_ENDPOINT: altera o endpoint de coleta padrão para um caminho personalizado, o que também pode reduzir a correspondência de regras.
O arquivo .env é um segredo de produção; não o envie ao Git nem o coloque em um diretório acessível pela web.
Crie docker-compose.yml:
nano docker-compose.yml
Escreva:
services:
umami:
image: ghcr.io/umami-software/umami:latest
container_name: umami
restart: unless-stopped
env_file:
- .env
environment:
DATABASE_URL: postgresql://umami:${POSTGRES_PASSWORD}@db:5432/umami
APP_SECRET: ${APP_SECRET}
TRACKER_SCRIPT_NAME: ${TRACKER_SCRIPT_NAME}
COLLECT_API_ENDPOINT: ${COLLECT_API_ENDPOINT}
DISABLE_TELEMETRY: "1"
depends_on:
db:
condition: service_healthy
ports:
- "127.0.0.1:3000:3000"
healthcheck:
test: ["CMD-SHELL", "curl -f http://localhost:3000/api/heartbeat || exit 1"]
interval: 30s
timeout: 5s
retries: 5
start_period: 30s
db:
image: postgres:15-alpine
container_name: umami-db
restart: unless-stopped
environment:
POSTGRES_DB: umami
POSTGRES_USER: umami
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
volumes:
- umami-db-data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U umami -d umami"]
interval: 10s
timeout: 5s
retries: 5
caddy:
image: caddy:2-alpine
container_name: umami-caddy
restart: unless-stopped
env_file:
- .env
ports:
- "80:80"
- "443:443"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile:ro
- ./caddy-data:/data
- ./caddy-config:/config
depends_on:
- umami
volumes:
umami-db-data:
Alguns pontos importantes aqui:
umamié vinculado apenas a127.0.0.1:3000; o mundo externo não consegue acessar a 3000 diretamente.- O PostgreSQL não mapeia a 5432; o banco de dados é usado apenas dentro da rede Docker.
- O que realmente fica exposto externamente são as portas 80 e 443 do Caddy.
DISABLE_TELEMETRY=1é opcional; ative se não quiser participar da telemetria anônima.
Uma abordagem mais estável em produção é fixar a versão da imagem do Umami em vez de usar latest a longo prazo. Na primeira implantação você pode usar latest para colocar no ar; para uso formal de longo prazo, recomenda-se consultar a versão estável atual no Umami GitHub Release ou no registro de imagens e depois fixar manualmente a tag.
Crie Caddyfile:
nano Caddyfile
Escreva:
{$UMAMI_DOMAIN} {
encode zstd gzip
reverse_proxy umami:3000
}
Abra o firewall:
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw reload
Se você usa um VPS de provedor de nuvem, também precisa liberar 80 e 443 no security group. Muitas falhas de certificado do Caddy acabam sendo porque o security group da nuvem não liberou as portas.
Execute:
cd /opt/umami
docker compose up -d
Verifique os contêineres:
docker compose ps
Verifique os logs:
docker compose logs -f --tail=100 umami
A primeira inicialização inicializa o banco de dados; esperar um ou dois minutos é normal. Abra no navegador:
https://analytics.example.com
A conta padrão é:
用户名:admin
密码:umami
Altere a senha imediatamente após o primeiro login. Não adie esta etapa; usar a senha padrão em um serviço público é um dos incidentes de segurança mais comuns.
Depois de entrar no painel, clique para adicionar um site e preencha:
- Nome do site: por exemplo
My Blog - Domínio: por exemplo
example.com
Após salvar, o Umami gera um trecho de rastreamento. Ele se parece mais ou menos com isto:
<script defer src="https://analytics.example.com/metrics.js" data-website-id="your-website-id"></script>
Coloque-o no <head> do seu site. Para a maioria dos blogs estáticos, temas WordPress e projetos Next.js, basta colocá-lo onde ele carrega em todas as páginas.
Se você só quer que o script tenha efeito em um domínio especificado, pode adicionar data-domains:
<script defer src="https://analytics.example.com/metrics.js" data-website-id="your-website-id" data-domains="example.com,www.example.com"></script>
Se você quiser respeitar a configuração Do Not Track do navegador, pode adicionar:
<script defer src="https://analytics.example.com/metrics.js" data-website-id="your-website-id" data-do-not-track="true"></script>
Depois de visitar seu site, volte ao painel do Umami; os dados geralmente aparecem em segundos ou dezenas de segundos.
Os bloqueadores de anúncios costumam bloquear caminhos óbvios de scripts de análise, como analytics, track, script.js, /api/send e similares.
O Umami oferece duas variáveis muito práticas:
TRACKER_SCRIPT_NAME=metrics.js
COLLECT_API_ENDPOINT=/api/web-events
Assim o script de rastreamento deixa de ser o script.js padrão, e o endpoint de coleta deixa de ser o caminho padrão. Alterar apenas o nome do script é incompleto; é melhor alterar também o endpoint de coleta. Isso não garante contornar 100% de todas as regras, mas é mais estável do que usar diretamente os caminhos padrão.
Depois de modificar .env, reinicie:
docker compose up -d
Depois copie novamente o código de rastreamento gerado no painel, ou altere manualmente o endereço do script no seu site para o novo caminho.
Observação: não engane os usuários nem contorne escolhas explícitas de privacidade em nome da análise. Se um usuário ativar o Do Not Track, recomenda-se respeitar.
Se o seu domínio de análise passa pelo proxy da Cloudflare, o Umami pode ver o IP do nó da Cloudflare em vez do IP real do visitante.
Você pode especificar o cabeçalho de IP do cliente nas variáveis de ambiente:
CLIENT_IP_HEADER=CF-Connecting-IP
Depois adicione em docker-compose.yml no umami.environment:
CLIENT_IP_HEADER: CF-Connecting-IP
Reinicie o Umami após a alteração.
Esta configuração só é adequada quando o tráfego realmente passa pela Cloudflare o tempo todo. Se o IP de origem puder ser contornado com conexões diretas, não confie cegamente em cabeçalhos CF-Connecting-IP fornecidos externamente; é melhor usar firewall ou security group para permitir apenas que os IPs de origem da Cloudflare acessem 80/443.
Se você não usa Cloudflare, ou usa apenas resolução DNS, não precisa configurar esta variável.
Os dados centrais do Umami estão todos no PostgreSQL. O mais importante é exportar o banco de dados regularmente.
Crie um script de backup:
nano backup-umami.sh
Escreva:
#!/usr/bin/env bash
set -euo pipefail
APP_DIR="/opt/umami"
BACKUP_DIR="$APP_DIR/backups"
DATE="$(date +%F-%H%M)"
mkdir -p "$BACKUP_DIR/$DATE"
cd "$APP_DIR"
docker exec umami-db pg_dump -U umami umami | gzip > "$BACKUP_DIR/$DATE/umami.sql.gz"
tar czf "$BACKUP_DIR/$DATE/umami-config.tar.gz" docker-compose.yml Caddyfile .env
find "$BACKUP_DIR" -mindepth 1 -maxdepth 1 -type d -mtime +14 -exec rm -rf {} \;
echo "Backup saved to $BACKUP_DIR/$DATE"
Adicione permissão de execução e teste:
chmod +x backup-umami.sh
./backup-umami.sh
ls -lh backups
Adicione uma tarefa agendada:
crontab -e
Backup todos os dias às 3 da manhã:
0 3 * * * /opt/umami/backup-umami.sh >> /opt/umami/backups/backup.log 2>&1
Backups locais só protegem contra erros, não contra falha de disco. Uma abordagem mais confiável é também sincronizar com rclone para armazenamento de objetos, um NAS ou outro VPS.
Antes de restaurar, prepare o mesmo docker-compose.yml, Caddyfile e .env. Os comandos de restauração abaixo assumem que o banco de dados de destino é um banco novo e vazio; se você quiser sobrescrever uma instância existente, pare primeiro a aplicação e confirme que deseja apagar os dados antigos, depois recrie o banco de dados ou o volume, para evitar misturar dados novos e antigos.
Inicie o banco de dados:
cd /opt/umami
docker compose up -d db
sleep 20
Restaure o SQL:
gunzip -c umami.sql.gz | docker exec -i umami-db psql -U umami umami
Depois inicie todos os serviços:
docker compose up -d
Após restaurar, verifique:
- Se consegue entrar no painel.
- Se a lista de sites existe.
- Se os dados históricos de visitas ainda estão lá.
- Se o script de rastreamento ainda usa o domínio atual.
Depois de escrever o script de backup, é melhor usar um VPS de teste para ensaiar uma restauração uma vez. Um backup sem ensaio de restauração é apenas consolo psicológico.
Faça backup antes de atualizar:
cd /opt/umami
./backup-umami.sh
Se usar latest:
docker compose pull
docker compose up -d
Verifique os logs após atualizar:
docker compose logs --tail=100 umami
A documentação oficial do Umami alerta que, após atualizações de versão principal, as estatísticas do PostgreSQL podem ficar desatualizadas, causando consultas lentas em instâncias grandes. Após atualizar, você pode entrar no banco de dados e executar:
docker exec -it umami-db psql -U umami -d umami
Depois execute:
ANALYZE;
Este comando atualiza as estatísticas do planejador de consultas do PostgreSQL e normalmente pode ser executado com segurança online.
No mínimo, faça isto:
- Altere a senha padrão imediatamente após o login.
- Não exponha 3000 e 5432 à internet pública.
- Use senhas fortes aleatórias para
APP_SECRETe a senha do banco de dados. - Não coloque
.enve os arquivos de backup em um diretório web. - Abra apenas 80, 443 e as portas SSH necessárias.
- Atualize regularmente o sistema e as imagens dos contêineres.
- Se o painel for só para você, você pode adicionar outra camada como Cloudflare Access, Tailscale ou WireGuard.
- Exclua prontamente membros que saíram, contas de terceirizados e contas temporárias.
Se você compartilha o Umami com uma equipe, também precisa prestar atenção a permissões e isolamento de sites. Não faça todos usarem a mesma conta de administrador.
Primeiro veja o status dos contêineres:
docker compose ps
Depois veja os logs do Caddy:
docker compose logs --tail=100 caddy
Verifique especialmente:
- Se o registro A do domínio está correto.
- Se o firewall do VPS libera 80/443.
- Se o security group da nuvem libera 80/443.
- Se a Cloudflare está com o modo de proxy errado ativado.
Ao solicitar o certificado pela primeira vez, recomenda-se colocar a Cloudflare primeiro em "somente DNS" e ativar o proxy conforme necessário depois que funcionar.
Veja os logs da aplicação:
docker compose logs --tail=100 umami
Causas comuns:
- A senha de
DATABASE_URLnão corresponde à senha de inicialização do PostgreSQL. .envfoi alterado, mas o volume antigo do banco de dados ainda tem a senha antiga.- O contêiner
dbainda não está healthy. - Erro de indentação no arquivo Compose.
Se você alterou a senha do banco de dados depois da primeira inicialização, o volume do PostgreSQL não muda automaticamente. Em ambiente de teste você pode excluir o volume e começar de novo; em produção você precisa entrar no banco de dados e alterar a senha.
Abra as ferramentas de desenvolvedor do navegador e verifique Network:
- Se
metrics.jscarrega com sucesso. - Se o endpoint de coleta retorna 200 ou 204.
- Se está sendo bloqueado por um bloqueador de anúncios.
- Se o CSP do site proíbe o carregamento de scripts externos.
- Se
data-website-idfoi copiado errado.
Se você usou data-domains, confirme que o domínio está escrito corretamente, incluindo www e não www.
Possíveis causas:
- Os bloqueadores de anúncios bloquearam algumas solicitações.
- Os usuários ativaram o Do Not Track.
- Seu script está apenas em algumas páginas.
- A integração com roteamento SPA ou framework frontend está incorreta.
- A CDN armazenou em cache o script errado.
Análise de sites nunca pode ser 100% precisa. Ela é mais adequada para ver tendências do que para ser tratada como números absolutos de nível financeiro.
Primeiro veja os recursos dos contêineres:
docker stats
Se as consultas do PostgreSQL estiverem lentas, você pode executar o comando mencionado antes:
ANALYZE;
Em instâncias com muito tráfego, também considere aumentar a memória do VPS, encurtar a retenção de dados ou migrar para um servidor de banco de dados mais potente.
Conclusão simples:
- Sites pequenos, blogs pessoais, sites de ferramentas, equipes pequenas: prefira o Umami.
- Alto tráfego, muita importância a relatórios bonitos e relatórios por e-mail: considere o Plausible.
- Quer algo mais leve, mais fácil de fazer backup e com menos manutenção: prefira o Umami.
- Já tem um VPS com 4 GB ou mais e aceita ClickHouse: o Plausible também é bom.
A versão auto-hospedada do Plausible exige PostgreSQL e ClickHouse. O ClickHouse tem desempenho de consulta forte, mas para um VPS pequeno é uma carga extra. O backup também não se resume a exportar um PostgreSQL.
A vantagem do Umami é ser leve o suficiente e simples o suficiente. Para a maioria dos administradores de sites, colocar a análise no ar, fazer bem os backups e configurar HTTPS é mais importante do que buscar um sistema de análise mais complexo.
Verifique antes do uso formal:
- O domínio já resolve para o VPS.
- 80/443 estão liberados no firewall e no security group.
- O Umami está vinculado apenas a
127.0.0.1:3000. - O PostgreSQL não expõe a 5432.
- As senhas em
.enveAPP_SECRETforam substituídas. -
APP_SECRETfoi registrado em um gerenciador de senhas e não será regenerado em atualizações futuras. - Você entrou no painel e alterou a senha padrão.
- Você adicionou o primeiro site.
- O script de rastreamento foi colocado no
<head>do site. - O painel Network mostra solicitações de coleta bem-sucedidas.
- O script de backup foi executado com sucesso.
- Você fez pelo menos um ensaio de restauração.
O Umami é melhor para responder a estas perguntas: as visitas aumentaram hoje, de onde vem o tráfego de busca, qual artigo é mais popular, qual país ou região visita mais e se a promoção recente teve efeito.
Ele não é adequado para análise de comportamento de usuário muito pesada, e não deve ser tratado como a única fonte de dados de negócio. Análise de sites é essencialmente uma ferramenta de tendências, não uma verdade absoluta.
Se você já tem um VPS, quer se afastar do Google Analytics e não quer manter uma pilha de análise mais pesada como o ClickHouse, o Umami é uma escolha muito adequada. É simples de implantar, tem backups claros e usa poucos recursos; para análise de visitas em blogs, sites de ferramentas, sites institucionais e projetos de equipes pequenas, é exatamente o que faz sentido.