- Reverse DNS (cached PTR lookups): IP hosts are stored with their name in 'host' and the IP in 'host_ip'; older IP-only logs are resolved on display and the host filter shows 'name (IP)'. RDNS / DNS_SERVER env. - Settings > Danger zone: delete all logs (type PURGE to confirm) through VictoriaLogs /delete/run_task; -delete.enable added to docker-compose. ALLOW_PURGE env to disable it. - Remove the custom YYYY-MM-DD - HH:MM:SS:mmm format; default is now the usual French display DD/MM/YYYY HH:MM:SS. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
5.9 KiB
Logstream
A simple syslog sink: receives logs over UDP/TCP on port 514, stores them in VictoriaLogs, and serves a clean web interface (light/dark theme, live search, live view, color tags, English/French UI).
devices ──514 udp/tcp──▶ logstream (Go) ──HTTP batches──▶ VictoriaLogs
▲ └── SSE (live) ──▶ browser
└──── API / UI ◀─────────┘
Getting started
cp .env.example .env # optional
docker compose up -d --build
./tools/send-test-logs.sh # sends 100 test messages
Then open http://localhost:8080.
Sending logs
- rsyslog (Linux): add
*.* @SERVER_IP:514(UDP) or*.* @@SERVER_IP:514(TCP) to/etc/rsyslog.d/90-logstream.conf, then runsystemctl restart rsyslog. - Network gear, NAS, firewalls: set the server IP and port 514 in their "remote syslog" settings.
- Manual test:
logger -n 127.0.0.1 -P 514 -d "hello error"(util-linux) orecho "<14>test ok" | nc -u -w1 127.0.0.1 514.
Supported formats: RFC 3164 (BSD) and RFC 5424. Over TCP, both "one message per line" and "octet counting" (RFC 6587) framing are accepted.
Search
Simple mode (default): each word is matched as a case-insensitive substring of the message, host and app. Words are combined with AND.
| Input | Meaning |
|---|---|
error disk |
contains "error" and "disk" |
"disk full" |
contains the exact phrase |
error -timeout |
contains "error" but not "timeout" |
LogsQL mode (Simple / LogsQL button): the full VictoriaLogs query language, e.g.
error AND host:web-01, app:~"ssh|nginx", or * | stats by (host) count().
The live view is disabled in this mode.
Each row shows, from left to right: the reception time (server clock, stored in the
received field), the timestamp found in the message itself, severity, host, app and message.
Logs stored before the received field existed show — in the first column.
Shortcuts: / focuses the search box, Esc clears it. Clicking a row shows all its fields.
Settings
The gear icon opens the settings panel:
- Language: English or French. The choice is remembered in the browser.
- Date & time: time zone (browser zone, UTC, or about 80 common zones) and the display
format of the reception time:
DD/MM/YYYY HH:MM:SS(default, the usual French display), with milliseconds,YYYY-MM-DD, 12-hour clock, ISO 8601 or Unix epoch. The time zone applies to every date shown. Remembered in the browser. - Danger zone: "Delete all logs" permanently erases every stored log (you must type
PURGEto confirm). Tags and settings are kept. VictoriaLogs needs-delete.enable(already set indocker-compose.yml); setALLOW_PURGE=falseto disable the feature. Anyone who can open the UI can purge: setAUTH_USER/AUTH_PASSif the UI is reachable by others.
Host names (reverse DNS)
When a device sends its IP address as host name (or no host name at all), Logstream looks up
its DNS name (PTR record) and stores the name in host and the IP in host_ip. Results are
cached (1 hour, 10 minutes when there is no name). Logs stored earlier with an IP are resolved
on display, and the host filter shows name (IP).
The container uses Docker's DNS, which forwards to the host's resolvers. If your local names
are only known by your router or a local DNS (Pi-hole, AdGuard, Unbound…), set
DNS_SERVER=192.168.1.1 (its address). Set RDNS=off to disable lookups.
- Color tags: each tag has a keyword, a background color (the text automatically
switches to black or white to stay readable) and options: whole word, match case,
regular expression, active. Tags are stored in
/data/tags.json(logstream-datavolume). Default tags:warning(orange),error(red),ok(green).
Configuration
| Variable | Default | Purpose |
|---|---|---|
SYSLOG_PORT |
514 |
syslog port published on the host |
HTTP_PORT |
8080 |
web UI port |
RETENTION |
30d |
how long VictoriaLogs keeps logs |
AUTH_USER / AUTH_PASS |
empty | HTTP Basic authentication for the UI |
RDNS |
on |
resolve IP hosts to DNS names |
DNS_SERVER |
empty | DNS server for reverse lookups (ip or ip:port) |
ALLOW_PURGE |
true |
allow "Delete all logs" in Settings |
TZ |
Europe/Paris |
time zone for RFC 3164 timestamps (which carry none) |
BATCH_SIZE, FLUSH_MS, QUEUE_SIZE |
1000, 1000, 100000 |
ingestion tuning |
Debugging
docker compose logs -f logstream: receive errors and errors sending to VictoriaLogs.- The bottom bar shows received / stored / dropped counters and the last storage error.
- http://localhost:9428/select/vmui: VictoriaLogs' own UI to try LogsQL queries.
- API:
curl 'localhost:8080/api/logs?q=error&range=1h&limit=5' # the response includes the generated LogsQL query curl localhost:8080/api/stats curl localhost:8080/api/tags - Running outside Docker (Go 1.22+):
VLOGS_URL=http://localhost:9428 DATA_DIR=./data SYSLOG_ADDR=:5514 go run .
Code layout
| File | Contents |
|---|---|
main.go |
configuration, startup, authentication |
syslog.go |
UDP/TCP listeners and RFC 3164 / 5424 parsing |
store.go |
batched inserts into VictoriaLogs and LogsQL queries |
query.go |
turns UI filters into LogsQL; live-view filter |
hub.go |
pushes new messages to browsers (SSE) |
rdns.go |
cached reverse DNS lookups |
tags.go |
color tag storage |
api.go |
/api/* HTTP routes |
web/ |
UI (HTML, CSS, plain JavaScript, no build step), embedded in the binary; translations live in web/app.js (I18N) |
Note
With Docker Desktop (macOS/Windows), the source IP seen by the container for UDP packets is
the Docker gateway. The host field still comes from the syslog header, which normally
carries the sender's real name.