A blazing-fast log tail & search server. Single binary, web UI, real-time streaming.
Quick Start • Features • Installation • API • License
🌐 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
| 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 | ✅ | ❌ | ❌ | ❌ |
- 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
# 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/appOpen http://localhost:7700 in your browser.
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/# Clone
git clone https://github.com/flolibio/tailr.git
cd tailr
# Build frontend + Rust binary
make build
# Or just run in dev mode
make devmake build-linux # x86_64
make build-linux-arm # aarch64
make release # both + frontendUses Docker with musl for static binaries (no glibc dependency).
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
# Initialize config file
tailr init
# Print config file contents
tailr config
# Use custom config file
tailr --config /path/to/config.tomlThe 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.
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 stopPID/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# 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# 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# Check for updates
tailr upgrade --check
# Upgrade to latest version
tailr upgradeNote: The upgrade replaces the binary atomically. If tailr is running as a service, you'll need to restart it after upgrading.
| 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) |
| 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=®ex=&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 |
// 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}# Terminal 1: Rust backend
cargo run
# Terminal 2: Vite dev server (with proxy)
cd frontend && npm run devVite proxies /api and /ws to http://localhost:7700.
make test # Run all checks (clippy + vue-tsc)
make test-backend # cargo test + cargo clippy
make test-frontend # vue-tsc --noEmitThe web UI supports multiple languages:
- English (en-US) — Default
- Chinese (zh-CN) — 简体中文
Adding a new language:
- Create a new locale file in
frontend/src/locales/(e.g.,ja-JP.json) - Copy the structure from
en-US.jsonand translate all strings - Update
frontend/src/locales/index.tsto include the new locale in the type definition - 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.
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)
- 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
