Building a Website Traffic Monitoring System Based on Umami
This article was last updated 287 days ago. The information within may have evolved or changed; if anything is outdated or broken, please feel free to leave a message in the comments section.
Article Abstract
To solve the problem of lacking intuitive statistical tools for website traffic sources, Umami was used to build a self-hosted traffic monitoring system. Based on the Docker Compose deployment scheme, service publishing is achieved by initializing a PostgreSQL database, configuring a reverse proxy, and domain name resolution. Combined with inserting tracking code into the header script of the WordPress theme, multi-dimensional traffic data collection is finally completed. This solution supports anonymized data processing and GDPR compliance, resolves abnormal geographical location identification issues by optimizing reverse proxy configurations, and provides lightweight, visualized access analysis capabilities for personal blogs and small sites.
Qwen3-14B · 2026-06-18

Note: The deployment content in this article is outdated. For the latest deployment tutorial, please refer to:Home Data Center Series: Detailed Setup Tutorial for the Latest Version of Umami (2.11.3), the initialization operations after successful deployment can still refer to this article.

Preface

Since the blog went online, I have researched a bunch of related technologies: health monitoring (uptime-kuma), failure message push (bark), web application firewall (SafeLine), etc., but lacked an intuitive way to view traffic sources.


To be fair, SafeLine actually allows for a simple overview, as shown below:

image.png

But on one hand, it is too rough since it's not dedicated to this, and on the other hand, this page cannot be extracted separately...


After searching the web, I found Umami: Umami is an easy-to-use, self-hosted open-source website traffic analytics tool. Umami does not use cookies, does not track users, and anonymizes all collected data, complying with GDPR policies. It has very low resource usage, and although its features are simple, the analyzed data is very rich.

The introduction looked good, so I decided to use it. The final result after setup is as follows:

image.png

image.png

image.png

image.png

Deploying Umami

Umami requires a database. By default, Umami supports two databases: MySQL and PostgreSQL. Following the convention of my previous articles, I would usually reuse MariaDB if possible, but Umami is a bit special: the database it uses requires special initialization, and a blank database won't work. Setting up a dedicated initialization is too much hassle (simplicity is key), so this article makes an exception and uses docker-compose to build it. I deployed Umami on a Tencent Cloud Lighthouse server.

Create the docker-compose.yml file

Create a docker-compose.yml file in the corresponding directory, in my case /docker/umami:

mkdir -p /docker/umami
cd /docker/umami
vim docker-compose.yml

cd /docker/umami

---
version: '3'
services:
  umami:
    image: ghcr.io/mikecao/umami:postgresql-latest
    ports:
      - "3000:3000"
    environment:
      DATABASE_URL: postgresql://umami:umami@db:5432/umami
      DATABASE_TYPE: postgresql
      APP_SECRET: replace-me-with-a-random-string
      TRACKER_SCRIPT_NAME: random-string.js
    depends_on:
      - db
    restart: always
    networks:
      - public-net
  db:
    image: postgres:15-alpine
    environment:
      POSTGRES_DB: umami
      POSTGRES_USER: umami
      POSTGRES_PASSWORD: umami
    volumes:
      - ./sql/schema.postgresql.sql:/docker-entrypoint-initdb.d/schema.postgresql.sql:ro
      - ./data:/var/lib/postgresql/data
    restart: always
    networks:
      - public-net

networks:
  public-net:
    external: true

vim docker-compose.yml
The content of docker-compose.yml is as follows:

mkdir /docker/umami/sql
mkdir /docker/umami/data

The sql and data directories need to be created in advance:
mkdir /docker/umami/sql

services:
  umami:
    networks:
      - public-net
  db:
    networks:
      - public-net

networks:
  public-net:
    external: true

The networks section

services:
  umami:
    networks:
      - default
  db:
    networks:
      - default

networks:
  default:
    name: public-net

services:

umami:
networks:- public-netdb:

vim /docker/umami/sql/schema.postgresql.sql

- public-net

drop table if exists event;'drop table if exists pageview;drop table if exists session;

First pull the images:

docker pull ghcr.io/mikecao/umami:postgresql-latest
docker pull postgres:15-alpine

public-net:external: true

Start the containers

cd /docker/umami
docker-compose up -d

If it is a newly created network, it should look something like this:http://宿主机IP:3000services:

image.png

umami:

networks:

image.png

image.png

Add a reverse proxy

- defaultLinux Panel Series: Configuring Reverse Proxy and Publishing Using Non-443 Ports。

Configure Umami

Add websites to be tracked

db:
networks:

image.png

- default
image.png

networks:

image.png

default:

Get the tracking code

Click the red box button in ”Settings” to get the tracking code:

image.png

The following interface will pop up:

image.png

Click the copy button below to get the tracking code.

Insert the tracking code

This configuration differs depending on the website building method. I used WordPress to build my site and used the Argon theme, which can be configured directly in Argon's ”Header Script“ option, as follows:

image.png

If it is other methods, you can find something like header.php, and then put it in<head></head>between the tags.

Optimization items

If the country/region appears as unknown, meaning the source cannot be tracked, you can add the following code in the reverse proxy configuration:

location = /api/collect remote_addr;proxy_add_x_forwarded_for;

Just replace the IP and port with your configuration.

For the final effect, see ”Top Menu” - “Other Functions” - “Traffic Monitoring” on this site:

image.png

View Related Categories · 3 Matches
📌 Content Structure Prompt:
This content is part of the following knowledge map, where you can view the complete content path: Blog Knowledge Map。
📎 Related Articles
Share this article
The blog content is original, please indicate the source when reposting! The RSS address of the blog is:https://blog.tangwudi.com/feed, welcome to subscribe; if needed, you can join theTelegram Groupto discuss questions together.
No Comments

Send Comment Edit Comment


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗ
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
Kaomoji
Emoji
Little Dinosaur
Flower!
Previous
Next
       

👋 Welcome to “Wudi's Personal Blog”

Here, long-term exploration is mainly carried out around the following directions:

🧱 Personal Digital Infrastructure and Blog System Construction
☁️ Cloudflare and Network Architecture Practice
🧠 AI and Knowledge System Exploration
🛡️ Network Security and Access Optimization
🎵 Music and Sound Cognition
👁️ Cognitive Perspectives and Worldviews