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/ and web/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:

  1. 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.

  1. 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

alt text

sudo docker logs liwan
#sudo docker stats liwan

Liwan is really lightweight ~10mb RAM taken!

During the first setup:

Liwan First Time Setup

You will create your admin user/pass:

Liwan Admin Creation

And finally, your Liwan web analytics dashboard:

Liwan Admin Panel UI

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!

Star History Chart

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.