Liwan - Project Overview
Liwan is an open-source, self-hosted web analytics platform designed for privacy-conscious developers and organizations.
Written in Rust and using modern web technologies, Liwan provides real-time insights without compromising user privacy.
- Description: Easy setup with a single binary and sub-1KB tracking script.
- Key Features: Quick setup, privacy-first, lightweight, real-time analytics, bot filtering.
- Modules: Backend API & CLI, web dashboard, tracker script, utility scripts, migrations, and test suite.
- Languages & Technologies: Rust (backend), TypeScript/JavaScript & Astro (frontend), Bash (scripts), SQL (DuckDB/SQLite migrations).
- Dependencies: Tokio, Poem, DuckDB, SQLite, Astro, React, D3, Bun.
- Configuration & Environment:
liwan.config.toml
, environment variables (LIWAN_CONFIG
,LIWAN_DATA_DIR
), Docker support. - Static Code Analysis: Strict typing in Rust and TypeScript, migration tests via Refinery, unit & integration tests in
tests/
andweb/src
.
Why This Matters 🚀
Self-hosting analytics empowers you with full control over your data, improves performance with a lightweight setup, and aligns with privacy regulations by avoiding third-party tracking.
And additionally, with Liwan we get:
- Quickly get started with Liwan with a single, self-contained binary .
No database or complex setup required.
The tracking script is a single line of code that works with any website and less than 1KB in size.
- Privacy first
Liwan respects your users’ privacy by default. No cookies, no cross-site tracking, no persistent identifiers. All data is stored on your server.
Module Descriptions
- Backend (
src/
): Core application logic including event processing, geoIP lookup, session management, and REST API built with Poem. - Database Migrations (
src/migrations/
): SQL migrations managed by Refinery for DuckDB and SQLite schemas. - Utilities (
src/utils/
): Helpers for hashing, geo lookup, referrer parsing, compression, and user-agent detection. - Web API & Server (
src/web/
): API routes for admin, authentication, dashboard data, and event ingestion; also embeds the frontend assets. - Web Frontend (
web/
): Astro-based dashboard with React components, D3-powered charts, and pages for login, settings, and project views. - Tracker Script (
tracker/
): Sub-1KB TypeScript module for sending pageview and custom events to the API. - Scripts (
scripts/
): Build, license aggregation, tracker bundling, demo deployment, and Dockerfile for container image. - Data (
data/
): Example configuration, GeoIP data, referrer and spammer lists, and asset samples. - Tests (
tests/
): Integration tests for authentication, dashboard functionality, and event handling.
Key Concepts and Algorithms
- Event Ingestion: Efficient, asynchronous handling of pageview and custom events using Tokio and channels.
- Bot & Crawler Filtering: User-agent analysis via
uaparser
and referrer lists to exclude non-human traffic. - GeoIP Lookup: Optional MaxMind integration or bundled DB for visitor geolocation.
- Query Caching: In-memory caching to reduce database load and speed up dashboard queries.
- Flexible Storage: Dual support for DuckDB and SQLite with connection pooling via
r2d2
. - Custom Graph Rendering: Client-side D3 implementation for performant, interactive charts.
Dependencies
- Rust Crates:
tokio
,poem
,poem-openapi
,duckdb
,rusqlite
,refinery
,serde
,tracing
,reqwest
,argon2
,md-5
, and others. - Frontend:
astro
,@astrojs/react
,react
,@tanstack/react-query
,d3-array
,d3-axis
,d3-geo
,d3-scale
,@radix-ui/react-accordion
, and related modules. - Tracker: Native Fetch API; no external runtime dependencies.
- Build & Deployment: Bash, curl, tar, rsync, Docker.
Liwan Deployment
Liwan can run as a standalone binary or inside a Docker container.
It listens on port 9042
by default and stores data in a local DuckDB or SQLite file.
Deploying with Docker
Use the provided multi-stage Dockerfile (with docker CLI) to quickly get started:
$ docker build -t liwan .
$ docker run -d \
-p 9042:9042 \
-e LIWAN_CONFIG=/config/liwan.config.toml \
-e LIWAN_DATA_DIR=/data \
-v $(pwd)/liwan.config.toml:/config/liwan.config.toml \
-v liwan_data:/data \
liwan
Liwan Docker Compose
If you prefere going the docker compose route to install Liwan:
#sudo docker logs liwan
#docker-compose -f liwan_docker-compose.yml up -d
#version: "3.8"
services:
liwan:
image: ghcr.io/explodingcamera/liwan:1.1
container_name: liwan #https://github.com/explodingcamera/liwan
ports:
- "127.0.0.1:80:9042"
volumes:
- liwan-data:/data
# See https://liwan.dev/reference/configuration for all configuration options
environment:
- LIWAN_BASE_URL=http://localhost #https://a.example.com
volumes:
liwan-data:
As you can see, no database involved. You will need a Proxy though!
sudo docker-compose up -d
#docker-compose -f liwan_docker-compose.yml up -d
sudo docker logs liwan
#sudo docker stats liwan
Liwan is really lightweight ~10mb RAM taken!
During the first setup:
You will create your admin user/pass:
And finally, your Liwan web analytics dashboard:
Configuration
Copy the example config and adjust as needed:
# liwan.config.toml
base_url = "http://localhost:9042"
port = 9042
[geoip]
# maxmind_account_id = "YOUR_ID"
# maxmind_license_key = "YOUR_KEY"
[duckdb]
# threads = 2
# memory_limit = "2G"
Conclusion
Liwan offers a compelling, privacy-first alternative to third-party analytics, combining Rust performance with a modern web dashboard.
Its minimal footprint allows it to run on modest hardware, giving you full control over your visitor data.
Self-hosting alternatives include Plausible, Umami, Matomo, GoatCounter, Countly…and the recently covered, Rybbit!
Latest Releases
At the time of writing, I got it working with the following commit, yet Liwan docker container version 1.1!
git log -1 --pretty=format:'%h %s (%ci)'
#9dc8716 chore: always checkpoint before shutdown (2025-05-15 20:55:12 +0200)
git describe --tags --abbrev=0
#liwan-v1.2.0-rc.10
git tag --sort=-v:refname | head -n 5
- Unreleased: Relicensed under Apache-2.0; updated DuckDB to 1.2; refreshed referrer and user-agent lists; UI improvements for long URLs; ARM64 container fixes; performance and memory optimizations.
- v1.1.0 (2024-12-28): Improved query caching; country codes for Google referrers; enhanced multi-user project access.
- v1.0.0 (2024-12-06): UTM parameter support; new date ranges; UI polish; bounce rate and average time metrics; D3-based graphs; optional favicon fetching.
- v0.1.1 (2024-09-24): Performance enhancements via database index optimizations.
- v0.1.0 (2024-09-18): Initial full release with live tracking, GeoIP, user management, filters, core metrics, and a clean UI.