Quand on lance un site web, la question arrive assez vite :
Comment savoir si les articles sont lus, quelles pages fonctionnent, et d’où viennent les visiteurs ?
Le réflexe classique, c’est Google Analytics. C’est puissant, très complet, et clairement installé dans le paysage. Mais pour un blog technique, un site perso ou un petit projet self-hosted, j’avais envie de quelque chose de plus simple.
Moins lourd. Plus lisible. Plus cohérent avec l’esprit UOpsLab.
C’est comme ça que je suis parti sur Umami, une alternative open source à Google Analytics que l’on peut héberger soi-même.
Léger
Un script discret, une interface claire, pas une usine à gaz.
Privacy friendly
Pas de cookies de tracking, pas de profilage publicitaire façon mammouth.
Self-hosted
Les statistiques restent sur votre infrastructure, avec votre stack.
Pourquoi choisir Umami ?
Umami est une plateforme d’analytics open source, pensée pour suivre l’essentiel sans vous noyer dans des menus interminables.
L’objectif n’est pas de remplacer toutes les fonctions marketing avancées de Google Analytics. L’objectif est plutôt de répondre clairement aux questions utiles :
- ➡️ combien de visiteurs passent sur le site
- ➡️ quelles pages sont consultées
- ➡️ d’où vient le trafic ;
- ➡️ quels pays, navigateurs et appareils ressortent ;
- ➡️ comment évoluent les visites dans le temps ;
- ➡️ quels événements personnalisés méritent d’être suivis.
Pour un blog ou un petit site vitrine, c’est largement suffisant.
Le bon niveau de détail
Quand on ne cherche pas à profiler les visiteurs ou à construire un tunnel marketing compliqué. Et qu’on veut juste comprendre ce qui intéresse les lecteurs, repérer les contenus utiles et améliorer son site sans collecter plus que nécessaire. Un produit open source comme Umami permet d’avoir cette finesse.
L’architecture utilisée
Voici la stack en place pour mon lab, volontairement classique :
- 🐳 Docker
- 🐘 PostgreSQL
- 🚦 Traefik
- 🔒 HTTPS automatique
- 🌐 un sous-domaine dédié, chez moi
umami.tondomaine.com.
Le flux reste simple :
Visiteur -> tondomaine.com -> script Umami
-> https://umami.tondomaine.com/api/send
Admin -> Traefik -> Umami
-> PostgreSQL
Je vous conseille de séparer Umami du site principal. Le site reste servi à part, et Umami vit sur son propre sous-domaine. C’est plus lisible, plus propre à maintenir, et plus simple à diagnostiquer quand quelque chose ne remonte pas. Validez bien la partie DNS maintenant :
- ➡️ Soit vous le faites à l’unité. Dans ce cas, c’est à créer manuellement dans votre zone DNS OVH, IONOS ou autre registrar.
- ➡️ Soit vous laissez Traefik faire le travail et vous redirigez
*.tondomaine.comvers le reverse proxy.
umami.tondomaine.com -> IP_PUBLIC_SERVEUR
ou
*.tondomaine.com -> IP_PUBLIC_TRAEFIK et vous gérez tout avec les labels ou la configuration dynamique
Préparer ses fichiers
Sur le serveur, je crée un dossier dédié en fonction de vos habitudes :
mkdir -p umami
cd umami
Puis un fichier .env pour isoler la configuration.
UMAMI_DOMAIN=umami.tondomaine.com
POSTGRES_DB=umami
POSTGRES_USER=umami
POSTGRES_PASSWORD=à changer avec le secret hex 16
APP_SECRET=à changer avec le secret base64 32
APP_SECRET est toujours très important, il sert à sécuriser l’installation. Il doit être unique et robuste. Pour générer les secrets, simple et efficace :
openssl rand -base64 32
openssl rand -hex 16
Maintenant le Docker Compose
Voici une base docker-compose.yml pour lancer Umami avec PostgreSQL derrière Traefik à adapter bien sûr.
services:
umami:
image: ghcr.io/umami-software/umami:latest
container_name: umami
restart: unless-stopped
init: true
depends_on:
umami-db:
condition: service_healthy
environment:
DATABASE_URL: postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@umami-db:5432/${POSTGRES_DB}
APP_SECRET: ${APP_SECRET}
CLIENT_IP_HEADER: x-forwarded-for
networks:
- umami-internal
- proxy
labels:
- "traefik.enable=true"
- "traefik.http.routers.umami.rule=Host(`${UMAMI_DOMAIN}`)"
- "traefik.http.routers.umami.entrypoints=websecure"
- "traefik.http.routers.umami.tls=true"
- "traefik.http.routers.umami.tls.certresolver=letsencrypt"
- "traefik.http.services.umami.loadbalancer.server.port=3000"
# Optionnel : limiter l’accès à l’interface Umami.
- "traefik.http.middlewares.umami-allowlist.ipallowlist.sourcerange=127.0.0.1/32,X.X.X.X/32"
- "traefik.http.routers.umami.middlewares=umami-allowlist"
healthcheck:
test: ["CMD-SHELL", "curl -f http://localhost:3000/api/heartbeat || exit 1"]
interval: 30s
timeout: 10s
retries: 5
umami-db:
image: postgres:16-alpine
container_name: umami-db
restart: unless-stopped
environment:
POSTGRES_DB: ${POSTGRES_DB}
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
volumes:
- ./postgres-data:/var/lib/postgresql/data
networks:
- umami-internal
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]
interval: 10s
timeout: 5s
retries: 5
networks:
umami-internal:
internal: true
proxy:
external: true
À adapter avant de copier-coller
- 🟠 Remplacez
X.X.X.X/32par votre IP publique si vous activez la whitelist. Si votre IP change souvent, gardez cette partie pour plus tard, sinon vous risquez surtout de vous enfermer dehors avec beaucoup d’élégance. - 🟠 Attention au network que vous avez en production
- 🟠 Les container_name, j’aime bien les rajouter pour s’y retrouver
Une fois OK, on lance simplement notre container :
sudo docker compose pull
sudo docker compose up -d
sudo docker compose logs -f
Première connexion
Une fois le conteneur lancé et une petite vérification du logs -f, on ouvre le navigateur.
Première connexion sur https://umami.tondomaine.com avec l’utilisateur admin et le mot de passe umami à changer tout de suite après connexion.

Ajouter le site à suivre
Dans Umami :
- 1 - Aller dans les paramètres.
- 2 - Ouvrir la section des sites web.
- 3 - Ajouter un nouveau site.
- 4 - Renseigner le nom et le domaine.

L’ajout du site génère ensuite le fameux Website ID, indispensable pour le tracking.
Umami fournit alors un script de ce genre :
<script
defer
src="https://umami.uopslab.com/script.js"
data-website-id="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
></script>
C’est ce petit bout de script qui va envoyer les pages vues vers votre instance.
Connecter Umami à Astro
Je prends l’exemple sur une intégration sur un site Astro, on peut mettre ce script directement dans le layout. Mais je préfère passer par des variables d’environnement, c’est plus propre et ça évite de figer un identifiant dans le code.
Dans .env :
PUBLIC_UMAMI_WEBSITE_ID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
PUBLIC_UMAMI_SCRIPT_URL=https://umami.uopslab.com/script.js
Puis dans le <head> du layout principal :
{
import.meta.env.PUBLIC_UMAMI_WEBSITE_ID && (
<script
defer
src={import.meta.env.PUBLIC_UMAMI_SCRIPT_URL}
data-website-id={import.meta.env.PUBLIC_UMAMI_WEBSITE_ID}
/>
)
}
Dans mon cas, j’ai poussé l’intégration un peu plus loin avec un composant Analytics.astro, pour centraliser Google Analytics, GTM et Umami au même endroit. Mais le principe reste exactement celui-là : si l’ID existe, on injecte le tracker.
Le piège avec Astro, Docker et les variables publiques
Petit retour d’expérience frais : avec Astro, les variables PUBLIC_* sont injectées au moment du build.
Ça veut dire que si vous générez une image Docker statique et que vos variables ne sont pas disponibles pendant npm run build, le HTML final sera construit sans le script Umami.
Et là, vous pouvez passer un moment à regarder le dashboard en vous demandant pourquoi rien ne bouge.
Dans mon cas, il fallait transmettre les variables au build Docker :
services:
site:
build:
context: .
args:
PUBLIC_UMAMI_WEBSITE_ID: ${PUBLIC_UMAMI_WEBSITE_ID:-}
PUBLIC_UMAMI_SCRIPT_URL: ${PUBLIC_UMAMI_SCRIPT_URL:-https://umami.uopslab.com/script.js}
Puis les récupérer dans le Dockerfile :
ARG PUBLIC_UMAMI_WEBSITE_ID
ARG PUBLIC_UMAMI_SCRIPT_URL=https://umami.uopslab.com/script.js
ENV PUBLIC_UMAMI_WEBSITE_ID=$PUBLIC_UMAMI_WEBSITE_ID
ENV PUBLIC_UMAMI_SCRIPT_URL=$PUBLIC_UMAMI_SCRIPT_URL
Ce n’est pas compliqué, mais c’est le genre de détail qui fait perdre du temps.
Vérifier que ça fonctionne
Une fois ce travail réalisé, on peut se rendre sur notre portail Umami, aller dans Sites et cliquer sur le site créé précédemment. Vous devriez commencer à voir des données remonter.

Petit délai d’affichage
Umami n’affiche pas toujours les données à la seconde près sur tous les écrans. Si vous avez un doute sur le bon fonctionnement avant de partir dans un gros diagnostic, il faut :
- ▫️ Aller sur votre site internet
- ▫️ Faire un petit
F12 - ▫️ Aller dans l’onglet Network
- ▫️ Filtrer les requêtes
/api/send
Si le Status Code est 200 OK, on est bon 😉
Google Analytics ou Umami ?
Je ne vais pas faire semblant : Google Analytics reste beaucoup plus complet. Si votre besoin est très marketing, avec de l’attribution avancée, des campagnes publicitaires et des rapports complexes, il a des arguments.
Mais pour un blog, un site vitrine, un projet perso ou une petite structure, Umami a un charme évident.
Google Analytics
- Très complet.
- Très puissant.
- Très intégré à l’écosystème Google.
- Mais parfois beaucoup trop dense pour un petit site.
Umami
- Simple à lire.
- Rapide à déployer.
- Self-hosted.
- Très cohérent pour un site orienté privacy et maîtrise des données.
Personnellement, je préfère un outil que je comprends, que je peux façonner, et qui me donne les bons indicateurs sans bruit inutile.
Et en plus, cet article est loin d’être exhaustif. Il existe encore de nombreuses fonctionnalités à explorer en affinant son utilisation, comme :
- ➡️ le suivi d’événements personnalisés
- ➡️ les clics sur boutons ou liens externes
- ➡️ l’analyse par source de trafic
- ➡️ le suivi par page ou catégorie d’articles
- ➡️ la comparaison de périodes
- ➡️ la segmentation par appareil, navigateur ou pays
- ➡️ le suivi des campagnes UTM
- ➡️ les objectifs marketing simples
- ➡️ les exports de données
- ➡️ la gestion multi-sites
- ➡️ le partage de dashboard, l’API pour créer ses propres tableaux de bord
- ➡️ …
Conclusion
Installer Umami en self-hosted est une très bonne première brique pour reprendre la main sur ses analytics.
Dans mon cas, avec Astro, Docker, PostgreSQL et Traefik, l’intégration est propre et reste facile à maintenir. On garde les statistiques utiles, on évite la lourdeur d’un gros outil marketing, et on reste cohérent avec une approche plus simple et plus respectueuse des visiteurs.