Open-source Docker app to browse, view, tail, and download server logs from
/app/logsvia a clean web UI. Supports folder navigation, live tail streaming, full file viewer with keyword search, and optional session-based auth. Built in Go on ascratchbase image (~8.62 MB).
- 📁 Browse nested log directories like a file explorer
- 👁️ View full file content with line numbers and keyword search
- ⬇️ One-click download for any log file
- 📡 Live tail via Server-Sent Events (SSE) with real-time keyword filter
- 🔍 Keyword search with highlight, prev/next navigation, and filter mode
- 🔃 Sortable table columns — click Name, Size, or Modified to sort (asc/desc)
- 🔐 Optional session-based login page (env-driven, no config files)
- 🗂️ Mount multiple services under
/app/logs/<service> - 🌐
BASE_PATHsupport for reverse proxy subpath deployments - 🐳 Final Docker image built on
scratch— ~8.62 MB, zero OS overhead - 🛡️ Path traversal blocked, logs mounted read-only,
HttpOnlysession cookies - 💚
/healthendpoint always public for container orchestrators
golang:alpine ── build stage (compiles static binary, CGO_ENABLED=0)
│
└── scratch ── runtime stage (binary + CA certs only, ~8.62 MB)
Edit docker-compose.yml to mount your service log directories:
volumes:
## Format: /host/path/to/logs:/app/logs/<service-name>:ro
- /app/api/logs:/app/logs/api:ro
- /app/identity/logs:/app/logs/identity:roEach mounted path becomes a browsable folder in the UI.
docker compose up -dClick ≡ View on any log file to open the full file viewer:
- Line numbers with scrollable content
- Search input (or press
Ctrl+F) — highlights all keyword matches in amber ↑/↓buttons orEnter/Shift+Enterto jump between matches- Filter toggle — hides non-matching lines entirely
- Files over 5 MB show only the last 5 MB with a warning banner
Click ⊞ Tail to open the real-time log tail:
- Streams new lines via Server-Sent Events as they are written
- Filter input in the toolbar — matching lines are highlighted, non-matching lines are dimmed
- ↺ Clear button to reset the stream and start fresh
- Auto-reconnects on disconnect
LogVault supports being served under a URL subpath via the BASE_PATH env var.
location /logvault/ {
proxy_pass http://logvault:8080/logvault/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}environment:
BASE_PATH: "/logvault"All internal links, redirects, breadcrumbs, form actions, and cookie paths are automatically prefixed.
Authentication is disabled by default. Set both env vars to enable the login page:
environment:
AUTH_USER: "admin"
AUTH_PASSWORD: "your-secret-password"| Behaviour | Detail |
|---|---|
| Auth disabled | All pages accessible without login |
| Auth enabled | Login page shown on first visit |
| Session TTL | 8 hours (in-memory, resets on container restart) |
/health |
Always public — never requires auth |
All endpoints are prefixed with BASE_PATH when set (e.g. /logvault/browse/).
| Endpoint | Description |
|---|---|
GET / |
Redirects to /browse/ |
GET /browse/ |
Root log directory browser |
GET /browse/<path> |
Browse a subdirectory |
GET /view/<path> |
View full file content with search |
GET /tail/<path> |
Live tail viewer page |
GET /tail-stream/<path> |
SSE stream endpoint (used by tail page) |
GET /download/<path> |
Download a log file |
GET /health |
JSON health check — always public |
GET /login |
Login page (only when auth is enabled) |
POST /logout |
Clears session cookie |
All configuration is via environment variables — no config files needed.
| Variable | Default | Description |
|---|---|---|
BASE_PATH |
(unset) | URL prefix for reverse proxy (e.g. /logvault). No trailing slash. |
AUTH_USER |
(unset) | Username for login. Auth disabled if blank. |
AUTH_PASSWORD |
(unset) | Password for login. Auth disabled if blank. |
PORT |
8080 |
Port the server listens on. |
Mount each service's log directory under /app/logs/<name>:
volumes:
- /app/api/logs:/app/logs/api:ro
- /app/identity/logs:/app/logs/identity:ro
- /var/log/nginx:/app/logs/nginx:roThis makes each service appear as a top-level folder in the browser.
| Stage | Base | Approx. Size |
|---|---|---|
| Build | golang:alpine |
~350 MB |
| Final | scratch |
~8.62 MB |
- Compiled with
CGO_ENABLED=0— fully static, no libc dependency - Mount logs as
:ro(read-only) to prevent any writes - Path traversal (
../../etc/passwd) is rejected viafilepath.Cleanprefix check - No shell or OS utilities inside the final image — minimal attack surface
- Session tokens are 16-byte cryptographically random hex strings
- Session cookie is
HttpOnlyandSameSite=Lax