Self-hosted service
msgbyte/tianji avatar
msgbyte/tianji

Tianji: Website Analytics, Uptime Monitoring and Server Status in One Self-Hosted Stack

Tianji: Insight into everything, Website Analytics + Uptime Monitor + Server Status. not only another GA alternatives

3,101 stars194 forksTypeScriptApache-2.0

At a glance

What is it?
Tianji bundles page-view analytics, uptime checks, server status, telemetry and a reporter binary into a single Docker Compose deployment. It is a reasonable fit for small teams who want one dashboard instead of three services, and a poor fit for anyone who needs deep, specialized monitoring.
Who is it for?
Adopt Tianji if you run a handful of sites and servers and want analytics, uptime checks and host status behind one login without operating three separate tools. Do not adopt it if you need Prometheus-style metric queries, long-retention time series, or an uptime monitor with a large library of notification integrations; the README describes a lightweight scope and does not promise those.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 2 days ago.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 30, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The three-tool problem Tianji is trying to collapse

The README's motivation section is unusually direct about the target user. It describes the common setup where a team runs GA or umami for page views and unique visitors, a separate uptime monitor for connectivity, and Prometheus for the status servers report back. Three dashboards, three sets of credentials, three upgrade paths. Tianji's answer is to put website analytics, an uptime monitor and server status into one application, and the README frames the trade-off honestly: specialized tools are better if you are an expert in the relevant discipline, but for lightweight needs an all-in-one application is more convenient.

That framing also defines who should not care. If your monitoring already runs on Prometheus with alerting rules and Grafana dashboards, Tianji's server-status feature is a simpler thing and will not replace it. The project's own roadmap lists telemetry as a first-class feature, which points at a second audience: maintainers of open source projects who want to know whether other people's deployments are alive, without building a telemetry endpoint themselves. The README's badge for Tianji Visitor is exactly that use case applied to Tianji itself.

How the pieces fit: tracker, server, reporter and PostgreSQL

The repository layout tells you the shape of the system. There is src/client for the frontend, src/server for the API and data layer, a reporter/ directory that is compiled separately, and packages/ plus apps/ for workspace packages. The Dockerfile confirms the split: one build stage compiles the reporter with Go (the stage image is golang:1.25.11-bookworm and the output binary is tianji-reporter), while the application stages run on node:22.22-alpine3.23 with pnpm installed globally.

Data flow follows the same division. A tracker script is built by the build:tracker script and collects page views; the server stores them and serves the dashboard. The reporter is a separate binary that runs on the machines you want to observe and reports back, which is why the roadmap has a line for "support passive reception of results" and separate lines for improving reporter usage, an uninstall guide, downloading from the server, and custom parameters. Notifications, OpenAPI, team collaboration, UTM tracking, waitlist, surveys and Lighthouse reports are all marked done on the roadmap, so the server is the integration point for all of them.

Two databases appear in the configuration. PostgreSQL is the default and is what docker-compose.yml provisions. The .env.example also lists CLICKHOUSE_URL, CLICKHOUSE_USER, CLICKHOUSE_PASSWORD and CLICKHOUSE_DATABASE, so ClickHouse is an optional backend the server can be pointed at. The README does not explain when to switch, and that gap matters if you expect a certain volume of events.

Installing Tianji with Docker Compose and logging in

The README's Docker Compose path is the shortest route. From the repository root, one command starts the application and its PostgreSQL database. The application is then reachable on port 12345, which is the port mapped in docker-compose.yml and documented in the README.

bash
docker compose up -d

The Compose file sets DATABASE_URL to postgresql://tianji:tianji@postgres:5432/tianji, so the app talks to the postgres service by its Compose service name. Two other values deserve attention before you expose the instance. JWT_SECRET is literally "replace-me-with-a-random-string" in the file, and ALLOW_REGISTER is set to "false", which means new accounts cannot self-register until you change it. PUBLIC_URL is empty and carries the comment "for example: https://app.tianji.dev".

If you prefer to run from source, the README gives a different first step: copy the example environment file into the server directory and set DATABASE_URL there.

bash
cp .env.example src/server/.env

The .env.example shows the expected shape of that value, with a schema parameter at the end: DATABASE_URL="postgresql://johndoe:randompassword@localhost:5432/mydb?schema=public". The same file sets ALLOW_REGISTER=false and ALLOW_OPENAPI=true by default, and notes that JWT_SECRET defaults to a daily string if you leave it blank, which is a reason to set it explicitly. The root package.json exposes the development entry points as pnpm dev, which runs the server and web client concurrently.

The reporter is where adoption gets harder

Website analytics needs one script tag. Server status needs an agent on every machine you want to watch, and that is the part of Tianji with the most operational weight. The repository ships a Go program under reporter/ that the Dockerfile compiles into a static binary, and the roadmap lists an uninstall guide, downloading from the server, and custom parameters as items under "improve monitor reporter usage". The fact that those are roadmap entries rather than long-settled features is the clearest signal in the README that reporter lifecycle management was still being filled in.

There is a practical consequence. Rolling the reporter out across a fleet means you own the deployment mechanism: how the binary gets to each host, how its parameters are set, and how you remove it later. The README does not document rollback, and it does not document a package repository for the reporter. If your hosts are managed by configuration management you already have a place to put this. If they are not, the reporter is the step where a weekend experiment turns into a project.

The Docker image adds its own constraints. The base stage installs python3, py3-pip, g++ and make for Apprise and Prisma, and pulls in Chromium plus fonts for Puppeteer, with a comment noting the Alpine version is pinned below 3.24 until Docker Hub static scans handle it reliably. That is a heavier image than a plain Node service, and it is the price of the Lighthouse report feature.

Where Tianji is the wrong tool

Tianji is not a metrics system. Nothing in the README or the configuration describes a query language, recording rules, or a time-series store you can interrogate the way you would query Prometheus. Server status here means the status servers report, presented in the dashboard, not an arbitrary metric pipeline.

It is also not a replacement for a dedicated uptime monitor if your requirements go beyond the basics. The project takes inspiration from uptime-kuma, which the README states is MIT licensed, but inspiration is not feature parity, and the README does not enumerate notification integrations or check types. If your on-call process depends on a specific paging provider, confirm that integration exists before you migrate.

The analytics side has a similar boundary. The README positions Tianji against GA and umami as a lighter option for page views, unique visitors and per-page counts, with UTM tracking listed as complete. It does not claim session replay, funnel analysis or warehouse export. Teams whose analysts write SQL against raw event tables will find the built-in views too coarse, and the ClickHouse options in .env.example are not explained well enough to plan around.

Finally, consider the single-database shape. In the Compose stack, the application and PostgreSQL run together, and the database volume is named tianji-db-data. Losing that volume loses analytics history. The README does not describe backup or restore procedures, so that responsibility is yours.

Tianji compared with running umami and uptime-kuma side by side

The obvious alternative is the combination the README itself names: umami for analytics and uptime-kuma for uptime, each self-hosted, each MIT licensed, each with its own database and its own upgrade cycle. The difference is not capability so much as shape. Those two tools each do one job and their interfaces reflect that focus. Tianji puts both jobs plus server status behind one login and one deployment.

That trade favors small teams. Two Compose stacks mean two sets of environment variables, two backup jobs, two upgrade windows, and a dashboard you have to visit twice. One stack means one of each. The cost is coupling: an upgrade to Tianji touches analytics, monitoring and server status at once, and a bug in the shared server affects all three. With separate tools, an analytics regression does not silence your uptime alerts.

The other difference is scope creep in the other direction. Tianji's roadmap already includes a waitlist, surveys, Lighthouse reports and team collaboration. If you want a tool that stays narrowly about page views, umami is the more predictable choice. If you want the surrounding features in the same place, Tianji is the one that has them. Neither answer is universal, and the README's own framing concedes the point about specialists.

Licence, release cadence and upgrade cost

Tianji is Apache-2.0. The README states this plainly and notes that it is inspired by umami and uptime-kuma, both MIT. Apache-2.0 is a permissive licence with an explicit patent grant, which is generally friendlier for corporate adoption than MIT in that one respect, but it also carries notice and attribution obligations when you redistribute. That is a description of the licence text, not legal advice; if you plan to ship Tianji inside a product, have counsel read it.

The release history in the repository shows a steady patch cadence: v1.32.34, v1.32.35 and v1.32.36 all landed within about a week, with the most recent push on 2026-09-09. The root package.json version is 1.32.37, one ahead of the latest tagged release. Frequent patch releases are convenient for fixes and annoying for operators, because each one is a redeploy. Nothing in the README describes an LTS branch or a skip-level upgrade policy.

The Dockerfile gives you one lever: the VERSION build argument is passed through as VITE_VERSION, so a self-built image can be stamped. The Compose file, by contrast, references the moonrailgun/tianji image with no tag, which means a fresh pull can move you to a new version without warning. Pinning that tag is the cheapest upgrade control available here.

Editorial conclusion

Adopt Tianji if you run a handful of sites and servers and want analytics, uptime checks and host status behind one login without operating three separate tools. Do not adopt it if you need Prometheus-style metric queries, long-retention time series, or an uptime monitor with a large library of notification integrations; the README describes a lightweight scope and does not promise those. Before committing, verify two things yourself: that the docker-compose.yml values (JWT_SECRET, ALLOW_REGISTER, PUBLIC_URL) match your deployment, and whether the reporter binary's install and uninstall flow fits your hosts, since the README only lists the reporter work as roadmap items.

Frequently asked questions

What is Tianji?

Tianji is a self-hosted application from msgbyte that combines website analytics, an uptime monitor and server status in one project, described in the README as an all-in-one insight hub and an alternative to running GA or umami alongside a separate monitor. It is written in TypeScript and licensed under Apache-2.0.

How do I install Tianji?

The README's Docker Compose path is to run docker compose up -d from the repository root, which starts both the tianji application and its postgres database. The application is then available at http://localhost:12345 by default.

Does Tianji need PostgreSQL?

Yes in the default setup. The Compose file points DATABASE_URL at a postgres service, and the .env.example shows a PostgreSQL connection string with a schema parameter. The same example file also lists CLICKHOUSE_URL and related ClickHouse settings, so an alternative backend appears to be supported, though the README does not explain when to use it.

Is Tianji free to use and what licence does it have?

The README states that Tianji is open source under the Apache 2.0 licence. It also notes that the project is inspired by umami and uptime-kuma, both of which are MIT licensed.

Official sources

  1. License: Apache-2.0
  2. msgbyte/tianji on GitHub
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/msgbyte-tianji.svg)](https://hysenlabs.com/projects/msgbyte-tianji)