1 Introduction
The previously set up umami (see article:Docker Series: Building a Website Traffic Monitoring System Based on Umami) version was 1.33.1:

while the latest official version on GitHub is already 2.11.3:

For someone with upgrade OCD, how could they tolerate this?? So I started the upgrade. However, after messing around for a long time, the version didn't change at all (later I found out the mirror address had expired), and I also noticed that after a while, Umami suddenly stopped receiving data (I suspect the website-id changed when redeploying Umami, but it didn't change on the dashboard), which was quite awkward.
But well, I thought I might as well take this opportunity to reorganize the installation method of umami. After all, when I set up umami before, I didn't know anything and followed someone else's tutorial step by step, not daring to make a single mistake. Now, after some practice, I have improved a bit. Plus, the current online tutorials for umami seem to be quite old, so it's time for an update. Thus, this article's journey of tinkering began.
However, based on the old saying: ”If there are difficulties, overcome them; if there are no difficulties, create difficulties and overcome them anyway,” I chose the more rugged path first this time: using the source code method to set up umami.
2 Setting up umami
1 Using git to set up umami via source code (not recommended, troublesome)
1.1 Prerequisites
Using PPA to install the latest nodejs:
curl -fsSL https://deb.nodesource.com/setup_20.x | bash -
apt-get install -y nodejs
Note 1: When I wrote this article, the latest nodejs from apt install was 18.13. If you directly use apt to install version 18.13, an error will occur later when installing umami, which is why I switched to the PPA method above for installation:

Note 2: Using this method already installs npm at the same time, so there is no need to install it separately using apt. Of course, if you insist on installing it separately with apt, it's not impossible, but you will encounter a bunch of errors—don't ask me how I know.
Installing git
apt install git
Installing yarn
npm install -g yarn
Installing pm2
npm install -g pm2
1.2 Installing and initializing the database

1.2.1 Using mariadb (use with caution, to be confirmed)
The instructions on GitHub state support for Postgresql (minimum supported version: v12.14) and MySQL (minimum supported version: v8.0). When I installed it using the docker-compose method before, I used Postgresql, but I was always a bit unsatisfied because I use mariadb more often and already have it ready. Since it supports MySQL, this time I prioritized using mariadb as the database (which turned out to be a failure).
If you don't have an existing mariadb database, it is still recommended to use docker to deploy mariadb (actually, from an OCD perspective, I should also install the mariadb database using the source code method, but deploying databases via docker is indeed too convenient for operations, so this time, even with my terminal-stage OCD, I had to compromise):
docker run --name=mariadb -d --restart=always \
-p 3306:3306 \ # 宿主机上映射到容器内部3306的端口,根据自己实际环境设置
-v /docker/mariadb/db:/var/lib/mysql \ # 映射宿主机上需要挂载目到mariadb容器内部的目录
-e MARIADB_ROOT_PASSWORD=yourpassword \# mariadb数据库root密码
mariadb:10.11
Note 1: When using, please remove # and the subsequent comment content yourself
Note 2: If you are more familiar with Postgresql, you can use it too, it doesn't matter which one you use (though looking at the results later, it actually does matter)
For the steps to initialize the database, please refer to the article:Tips and Tricks Series: Creating a New Empty Database and Granting Permissions to Corresponding Users, here we assume we create a new database named ”umami”, and create an account with both username and password as umami, which has full permissions on the umami database.
1.2.2 Using Postgresql
The command to deploy postgresql in docker run format is as follows:
docker run --name postgres -d --restart=always \
-p 5432:5432 \
-e POSTGRES_USER=umami \
-e POSTGRES_PASSWORD=umami \
-e POSTGRES_DB=umami \
-e PGDATA=/var/lib/postgresql/data/pgdata \
-v /docker/postgres/data:/var/lib/postgresql/data \
postgres:15.4
Note: The most convenient thing about using postgresql is that the initialization process is completed using the -e parameter. However, I suppose mariadb should be able to do this too. I haven't paid much attention to it before because many databases were manually initialized by myself later, and I've gotten used to it. I'll look into it when I have time in the future.
1.3 Installing umami
Choose an installation directory; I am used to installing directly in the root folder:
cd ~
git clone https://github.com/umami-software/umami.git
cd umami
yarn install
Success:

Create a new .env file and fill in the database information in the following format:
DATABASE_URL=mysql://umami:umami@localhost:3306/umami #选择mariadb或者mysql
DATABASE_URL=postgresql://umami:umami@localhost:5432/umami #选择postgresql
TRACKER_SCRIPT_NAME=tangwudi #这个很重要,自定义js脚本名字,可以不用加js结尾,我后面解释
Note 1: localhost:3306 indicates that the database and the umami program are on the same device. If the database is on a different host, localhost needs to be changed to the IP address of that host.
Note 2: Choose different database links for DATABASE_URL based on your selected database, pick one of the two.
Building umami:
yarn build
Attention!!!! If using mysql or mariadb, I encountered the following error:

Solution: Open the package.json file under the umami folder (installing from source, the package.json file is equivalent to the docker-compose.yml file in the docker-compose installation method; if you need to change default configuration information such as ports, modify it here):

Replace the content of line 23 in the red box of the image above:
"build-db": "npm-run-all copy-db-files build-db-client",
with the following content:
"build-db": "npm-run-all copy-db-files build-db-client resolve-db",
"resolve-db": "prisma migrate resolve --applied '05_add_visit_id'",

Then run the command again
yarn buildto build it.
Build successful:

Update the browserslist:
npx update-browserslist-db@latest

Test if umami can start normally:
yarn start
For formal use, you need to enable umami in the background:
pm2 start yarn --name "umami" -- start

Automatically start pm2 on boot and save the currently running umami process:
pm2 startup
pm2 save

Note: When using the pm2 process manager, if you want to stop and delete related processes, use the following commands:
pm2 list #查看有哪些pm2进程id
pm2 stop 进程id
pm2 delete 进程id
Actually, it just uses pm2 instead of the regular service settings, which feels quite easy to use.
Then directly usehttp://部署机IP:3000to access it. Depending on the chosen database, there are 2 outcomes, at least from what I encountered:
mysql or mariadb
After adding the website, the dashboard directly displays an error:

Where on earth is the problem: Could it be that when solving theyarn buildP3009 error earlier, I actually referred to the method of handling similar problems when building umami with Vercel, and this handling didn't adapt well? Because the actual handling method affected the generation of the database, and I got the same problem whether I switched to mysql or mariadb. To verify this judgment, I switched to postgresql. Unexpectedly, there was no error during the build, it passed directly, and the dashboard didn't encounter the ”An error occurred” error later.
I went to look at those deployed from source online, and there are plenty of P3005, P3009, and similar issues during upgrades (due to incompatibility between mysql 5.7 commands and the new 8.x, requiring modification of the corresponding commands in the sql file used during initialization). Thinking about it now, the reason why the umami I deployed using docker-compose earlier had issues was also because I foolishly tried to upgrade it not long ago... It seems upgrading umami still requires caution, especially when using mysql/mariadb, because it involves some command changes from mysql 5.7 to the new version 8.x, making it particularly prone to issues.
postgresql
This way there is no problem:

2 Using docker to set up umami (recommended for most people, I will use it next time too)
2.1 Creating the docker-compose.yml file
Create a docker-compose.yml file in the corresponding directory, in my case /docker/umami:
mkdir -p /docker/umami/data #data目录是后面postgresql挂载的时候要用,这里提前创建好
cd /docker/umami
vim docker-compose.yml
When building umami using docker-compose previously, the image address used was relatively old and seems to be inaccessible now (image address: docker.umami.is/umami-software/umami:postgresql-latest). This time I used the latest official one. Based on the official yml provided by umami on GitHub and the yml in my previous article on building umami with docker-compose, I made some modifications to the content. Below is the current latest docker-compose.yml file content:
version: '3' {POSTGRES_USER} -d{POSTGRES_DB}"]
Note: Compared with the yml content in the previous article, it can be seen that a sql file (schema.postgresql.sql) required for initializing postgresql has been removed because it is no longer needed. The initialization content is already built into the umami program. In the official folder on GitHub, you can actually see the initialization steps and content of the postgresql database:

mysql/mariadb is similar:

2.2 Pulling images
docker pull ghcr.io/umami-software/umami:postgresql-latest
docker pull postgres:15-alpine
2.3 Starting containers
cd /docker/umami
docker-compose up -d
Then, just like the previous steps for deploying from source, directly usehttp://部署机IP:3000method.
Tested it, and it is indeed the latest version:

Note: I spent 2 days researching deployment from source. Although it was mainly because I chose mariadb as the database at the beginning, even if you are skilled and don't take detours, it still takes about ten minutes to deploy once, not to mention the strange problems that might be caused by differences in different environments. On the other hand, building it using docker-compose, does it even take 30 seconds?? So for umami, it is recommended that ordinary people do not mess with the source code when building it.
3 Optimizing umami configuration
For detailed initialization configuration, please refer to my previous article. I won't repeat it here. I will only talk about a few key optimization points that were not mentioned before.
Prevent being blocked by ad-blocking plugins
The default js script name for umami is ”script.js” or ”umami.js”. This kind of name makes it obvious what it does and is not stealthy at all. To prevent it from being directly blocked by ad-blocking plugins, you need to disguise it and change it to a name that is not easily detected, for example, I changed it to ”tangwudi”~. If installed via docker-compose, you need to add the environment variable in ”docker-compose.yml”:
environment:
TRACKER_SCRIPT_NAME: tangwudi
If installing from source, you need to add it to the .env file
TRACKER_SCRIPT_NAME=tangwudi
Note: For deployment from source, it must be added before runningyarn buildotherwise, if added afterwards, an error will occur where the tracking code changes to tangwudi but the page cannot be found when accessed, and only accessing ”script.js” still works, forcing me to rebuild it again; similarly, when installing via docker-compose, it needs to be before runningdocker compose up -dthe command.
Place the JS script (tangwudi in this example) on object storage
Essentially, umami's tracking method is to run a JS script through the browser and then send the results back to the host where umami is deployed to complete the statistics. Therefore, in theory, it doesn't matter where the script is placed, as long as the browser can read it. For example, I can place the JS script on Cloudflare R2 (if it is a domestic server, it can be placed on a domestic cloud provider's COS, such as Tencent's COS) and enable CDN. This can minimize back-to-origin requests, which is achieved by modifying the ”src” part of the tracking code:
src="https://r2.tangwudi.com/tangwudi" # 假设r2.tangwudi.com是我r2存储桶的自定义域名
However, I think if there is a CDN, this can just be cached directly on the CDN. After all, it is just a piece of static content and won't frequently request back-to-origin. Moreover, this option must be used in conjunction with the next optimization parameter ”data-host-url”, which feels like a lot more trouble. Because if there is no ”data-host-url” parameter, the address in src will be directly used as the server address for umami to receive tracking data, saving a lot of hassle.
Specify the actual server address for receiving tracking data
data-host-url="https://umamiserver.tangwudi.com" #实际部署umami的服务器访问域名
This is generally used in conjunction with the previous parameter, depending on personal choice.
Limit display to collected information of a specific domain only
data-domains="blog.tangwudi.com"
This option is actually very useful in theory. For example, my WordPress can be accessed directly using the intranet address at home, or directly using the Tailscale address outside. Before I added this option, accesses to these addresses would be displayed on the monitoring page, which even triggered an SSRF (Server-Side Request Forgery) attack on me, simply because the intranet address 192.168.x.x of my WordPress server was displayed on the monitoring interface.
Note: Why do I say "in theory"? Because I feel like I was fooled. The final generated share link looks like this:

It just added ”/blog.tangwudi.com” after the original share link??? Crucially, it can also be directly removed and still be accessed. Once removed, is it just like before where any address can be seen??
Ultimately, my tracking code is as shown in the figure below (only using the first and fourth optimization options):

4 Upgrading umami
1.1 Source code deployment method
Three steps:
git pull #在umami文件夹下操作
yarn install
yarn build
1.2 docker-compose method
docker compose pull
docker compose up --force-recreate
It seems quite simple, but based on the English posts I browsed over the past few days to solve the strange issues caused by using the MariaDB database, as well as the trigger for writing this article, upgrading umami should still be done with caution. Especially when there is a large version gap (even a small one might not be safe), it is recommended to back up the database content first.
5 Summary
At least for umami, the source code deployment method is indeed too much hassle (later, to verify whether the dashboard error when using the MariaDB database was caused by environmental reasons, I specially set up a brand new Debian 12 LXC environment, so the current umami is actually running on LXC, connected to PostgreSQL deployed via Docker, too lazy to hassle with it anymore). The docker-compose deployment method is recommended.
The display of the new version is slightly better than before, with an additional display of the number of visits:

There is also an additional behavior category, not sure what it is, will check after 1 day:

You can use the link below to view the actual effect of the new version of umami:Demo link for the new version of umami。
Unable to start, strange
In what way was it deployed that it cannot start? What is the error message?