Skip to content

flolibio/tailr

Repository files navigation

tailr

tailr

A blazing-fast log tail & search server. Single binary, web UI, real-time streaming.

Release Stars License Build

Quick StartFeaturesInstallationAPILicense


Demo

🌐 Live Demo: tailr.flolib.com

Real-time log tailing with multi-keyword filtering:

  • 📡 WebSocket-based live streaming
  • 🔍 Regex search with mmap
  • 🎨 Configurable log levels with color coding
  • 🔒 Optional token authentication

Why tailr?

Feature tailr kail goaccess lnav
Single binary
Web UI
Real-time tail
Regex search
Log level detection
Memory-mapped
Self-upgrade
Token auth
Config presets

Features

  • Real-time tail — WebSocket-based live log streaming
  • Multi-keyword filter — AND logic, like grep kw1 | grep kw2
  • Fast search — mmap-based grep with regex support
  • Configurable log levels — User-defined levels, keywords, and colors with 7 presets (General, Java, Python, PHP, Go, Rust, syslog)
  • Single binary — No dependencies, no runtime, just run
  • Web UI — Built-in Vue 3 SPA, no separate frontend deployment
  • Log rotation aware — Detects inode changes, handles logrotate
  • Self-upgrade — One command to update to the latest version
  • Token authentication — Optional Bearer token for secure access
  • Path validation — Prevents directory traversal attacks
  • Multi-language UI — English (default) and Chinese, with easy extensibility
  • Cross-platform — Linux (x86_64/ARM64), macOS

Quickstart

# Run with specific log directories
tailr --log /var/log/app /var/log/nginx

# Run with a single file
tailr --log /var/log/syslog

# Custom bind address
tailr --log /var/log -b 127.0.0.1:8080

# With authentication
TAILR_TOKEN=your-secret tailr --log /var/log/app

Open http://localhost:7700 in your browser.

Installation

Download binary

Download the latest binary from GitHub Releases.

# Linux x86_64
curl -LO https://github.com/flolibio/tailr/releases/latest/download/tailr-x86_64-linux-musl.tar.gz
tar xzf tailr-x86_64-linux-musl.tar.gz
sudo mv tailr /usr/local/bin/

# Linux ARM64
curl -LO https://github.com/flolibio/tailr/releases/latest/download/tailr-aarch64-linux-musl.tar.gz
tar xzf tailr-aarch64-linux-musl.tar.gz
sudo mv tailr /usr/local/bin/

Build from source

# Clone
git clone https://github.com/flolibio/tailr.git
cd tailr

# Build frontend + Rust binary
make build

# Or just run in dev mode
make dev

Cross-compile for Linux (from macOS)

make build-linux       # x86_64
make build-linux-arm   # aarch64
make release           # both + frontend

Uses Docker with musl for static binaries (no glibc dependency).

CLI

tailr [OPTIONS]           # Start server (default)
tailr <COMMAND>           # Run a subcommand

Commands:
  init                    Initialize config file
  config                  Print config file contents
  stop                    Stop running daemon
  status                  Show daemon status
  systemd                 Generate systemd service file
  launchd                 Generate launchd plist file (macOS)
  upgrade                 Check for updates and upgrade tailr to the latest version

Options:
  -l, --log <LOG>...         Log directories or files to serve (can specify multiple)
  -b, --bind <BIND>          Bind address [default: 0.0.0.0:7700]
  -d, --daemon               Run as daemon in background
      --config <CONFIG>      Custom config file path
      --pid-file <PID_FILE>  Custom PID file path
      --log-file <LOG_FILE>  Custom log file path for daemon mode
  -h, --help                 Print help
  -V, --version              Print version

Priority: CLI args > Config file > TAILR_* env vars > Defaults

Config File

# Initialize config file
tailr init

# Print config file contents
tailr config

# Use custom config file
tailr --config /path/to/config.toml

The config file is located at ~/.config/tailr/config.toml by default:

# Log directories or files to serve
log = ["/var/log"]

# Server bind address
bind = "0.0.0.0:7700"

# Token for authentication (empty = no auth required)
token = ""

# Log level configuration (optional, uses "general" preset by default)
[log_levels]
preset = "python"

[[log_levels.levels]]
name = "CRITICAL"
keywords = ["CRITICAL"]
colorLight = "#CC2D26"
colorDark = "#FF6B63"

[[log_levels.levels]]
name = "ERROR"
keywords = ["ERROR"]
colorLight = "#A32D2D"
colorDark = "#F09595"

[[log_levels.levels]]
name = "WARNING"
keywords = ["WARNING"]
colorLight = "#854F0B"
colorDark = "#EF9F27"

[[log_levels.levels]]
name = "INFO"
keywords = ["INFO"]
colorLight = "#0C447C"
colorDark = "#85B7EB"

[[log_levels.levels]]
name = "DEBUG"
keywords = ["DEBUG"]
colorLight = "#3B6D11"
colorDark = "#97C459"

Available presets: general, java, python, php, go, rust, syslog

Log levels can also be configured via the Web UI under Settings → Log Levels.

Daemon Mode

Run tailr as a background daemon instead of using nohup:

# Start in daemon mode
tailr -d -l /var/log/app /var/log/nginx

# Check status
tailr status

# Stop daemon
tailr stop

PID/Log files are stored in ~/.local/share/tailr/ by default. Customize with:

tailr -d -l /var/log/app \
  --pid-file /run/tailr.pid \
  --log-file /var/log/tailr.log

System Service

systemd (Linux)

# Generate and install service file
tailr systemd -l /var/log/app | sudo tee /etc/systemd/system/tailr.service

# Enable and start
sudo systemctl enable --now tailr

# Check status
sudo systemctl status tailr

launchd (macOS)

# Generate and install plist
tailr launchd -l /var/log/app > ~/Library/LaunchAgents/com.tailr.plist

# Load and start
launchctl load ~/Library/LaunchAgents/com.tailr.plist

# Check status
launchctl list | grep tailr

Self-Upgrade

# Check for updates
tailr upgrade --check

# Upgrade to latest version
tailr upgrade

Note: The upgrade replaces the binary atomically. If tailr is running as a service, you'll need to restart it after upgrading.

Environment Variables

Variable Default Description
TAILR_LOG_DIR <exe_dir>/logs Comma-separated log directories
TAILR_BIND 0.0.0.0:7700 Listen address
TAILR_CONFIG ~/.config/tailr/config.toml Config file path
TAILR_TOKEN Authentication token (overrides config file)
RUST_LOG Tracing filter (e.g. tailr=debug)

API

Route Method Description
/api/files GET List log files (filtered: text files only)
/api/file/content GET Paginated file content (?path=&offset=&limit=)
/api/file/tail GET Last N lines (?path=&lines=)
/api/file/info GET File metadata + line count
/api/search GET Grep search (?path=&q=&regex=&levels=&context=&limit=)
/api/config/log-levels GET Get current log level configuration
/api/config/log-levels POST Save log level configuration (hot-reload + persist to config.toml)
/api/health GET Status + uptime + version
/ws WS Real-time log streaming

WebSocket Protocol

// Subscribe to a file
{"type": "subscribe", "path": "/var/log/app.log"}

// Receive new entries
{"type": "append", "path": "/var/log/app.log", "seq": 42, "entries": [...]}

// Catchup on reconnect
{"type": "catchup", "path": "/var/log/app.log", "entries": [...], "lastSeq": 100}

Development

# Terminal 1: Rust backend
cargo run

# Terminal 2: Vite dev server (with proxy)
cd frontend && npm run dev

Vite proxies /api and /ws to http://localhost:7700.

Testing

make test              # Run all checks (clippy + vue-tsc)
make test-backend      # cargo test + cargo clippy
make test-frontend     # vue-tsc --noEmit

Internationalization (i18n)

The web UI supports multiple languages:

  • English (en-US) — Default
  • Chinese (zh-CN) — 简体中文

Adding a new language:

  1. Create a new locale file in frontend/src/locales/ (e.g., ja-JP.json)
  2. Copy the structure from en-US.json and translate all strings
  3. Update frontend/src/locales/index.ts to include the new locale in the type definition
  4. Add the locale option to the language switcher in SettingsPanel.vue

The language preference is persisted in localStorage and auto-detected from the browser on first visit.

Architecture

src/main.rs           # CLI (clap), env vars, starts axum server
src/config.rs         # Config loading (figment), presets, persistence
crates/
  protocol/           # Shared types: LogEntry, WSMessage, LevelDef, LogLevelConfig
  tail-engine/        # File watching (notify), LineIndex (mmap), TailSession
  search-engine/      # Grep-based search, LevelDetector (dynamic log levels)
  server/             # Axum app: REST API, WebSocket, static files
frontend/             # Vue 3 + TypeScript + Vite SPA
  composables/        # useLogLevels (presets, colors, dynamic CSS)
  components/         # Settings UI (LogLevelSettings, ColorPicker)

Security

  • Token Authentication — Optional Bearer token via config, environment variable, or Web UI
  • Path Validation — All file endpoints validated against configured directories
  • CSRF Protection — Restricted CORS headers + X-Requested-With check
  • Error Sanitization — Generic error messages to client, detailed logs server-side

License

MIT