A working log server takes one binary and about fifteen minutes.
This page walks the whole path: download, TLS, service install, shipping logs from your hosts, the first useful query, then retention, backups and an alert. Every command below is one you can paste.
No Docker. No database. No JVM. Nothing to install first.
SSH to the server and grab the binary for your architecture:
wget https://downloads.eligian.com/centrallogging-linux-amd64.zip
unzip centrallogging-linux-amd64.zip
Let it bind the privileged ports without running as root:
sudo setcap CAP_NET_BIND_SERVICE=+eip centrallogging-linux-amd64
Then start it:
./centrallogging-linux-amd64
Open your domain. You get a setup screen. Fill in the admin email, which is also the address Let’s Encrypt uses for the certificate.
Confirm HTTPS works before going further. If the certificate did not issue, the usual cause is DNS that has not propagated or port 80 blocked upstream.
Then stop it with Ctrl+C.
So it survives a reboot:
sudo ./centrallogging-linux-amd64 -install
sudo systemctl enable centrallogging
sudo systemctl start centrallogging
Behind a reverse proxy instead? Set PORT to anything other than :80 and terminate TLS yourself:
PORT=:8080 ./centrallogging-linux-amd64
A log source is a stream of logs with its own database, its own retention setting, and its own token. Create one per application or per host group — whatever grouping you want to search separately.
Create it in the web UI. Copy the token it gives you. That token is what authenticates ingest, so treat it like a password.
One line:
curl -X POST https://logs.example.com/api/v1/log/{log-source-token} -d "this is a log entry"
Structured JSON works the same way, and pays off later when you query:
curl -X POST https://logs.example.com/api/v1/log/{log-source-token} \
-d '{"level": "error", "msg": "something went wrong"}'
For batches, send a file. Every newline becomes a log entry:
curl -X POST https://logs.example.com/api/v1/ingest_logs/{log-source-token} -d @mylogs.txt
Prefer a header to a token in the URL? Use a Bearer token:
curl -X POST https://logs.example.com/api/v1/ingest_logs \
-H "Authorization: Bearer {log-source-token}" \
-d @mylogs.txt
Gzip is supported for large batches:
curl -X POST https://logs.example.com/api/v1/ingest_logs/{log-source-token} --data-binary @mylogs.gz
The clagent binary ships system logs upstream on a schedule. On Linux it reads systemd via journalctl. On OpenBSD it reads syslogd.
Install it on each host you want logs from:
wget https://downloads.eligian.com/clagent-linux-amd64.tar.gz
tar xzf clagent-linux-amd64.tar.gz
Create /etc/clagent.toml:
URL = "https://logs.example.com/your-log-source-token"
Then install it as a service:
sudo ./clagent-linux-amd64 -install
sudo systemctl enable clagent
sudo systemctl start clagent
The agent pushes outbound over HTTPS. Nothing needs to reach into your hosts, which keeps the firewall rules simple. It also sends host check-ins, so you get host monitoring with no extra work.
For a fleet, use the Ansible playbook in the agent docs instead of doing this by hand.
Two modes, toggled from the search page.
Full-text search for the quick look:
description:water
+description:water -light beer
/light (beer|wine)/
SQL when you need real answers. Logs live in a logs table with timestamp and msg columns, and json_extract reaches into structured messages:
SELECT
"timestamp",
json_extract(logs.msg, '$.Data.method') AS method,
json_extract(logs.msg, '$.Data.request_uri') AS request_uri,
json_extract(logs.msg, '$.Data.addr') AS addr
FROM logs
WHERE json_valid(msg) AND request_uri LIKE '%/account%'
ORDER BY "timestamp" DESC
LIMIT 2001;
Which hosts are actually sending logs? This is the first query to run after any install:
select source, count(source) as log_count
from logs
group by source
order by log_count desc;
If a host you configured is missing from that list, the agent on it is not working.
More in useful log queries.
Each log source has a Retention Days setting. It defaults to 15. Raise it if you have disk and a reason, lower it if you are storing something sensitive.
Retention is the setting people forget until the disk is at 98%. Set it on day one.
Nightly backups upload the main database and every per-source log database to S3. Set them in the Settings page, or with environment variables:
AWS_ACCESS_KEY_ID=...
AWS_SECRET_ACCESS_KEY=...
BACKUP_AWS_REGION=us-east-2
BACKUP_S3_BUCKET=cl-backups
Self-hosting the backups too? Point BACKUP_S3_ENDPOINT at a Garage or MinIO server:
BACKUP_S3_ENDPOINT=https://s3.example.com:3900
BACKUP_AWS_REGION=garage
Values saved in the web UI take precedence over the environment variables. Backups older than 15 days are removed automatically.
A log server nobody looks at is a log server that tells you nothing. Create at least one alert on day one.
Alert rules run a SQL or FTS query every 5 minutes. Set a Max Frequency so a noisy condition does not page you forty times.
The condition can also fire when a query returns nothing. That is how you catch a job that stopped running rather than one that failed loudly.
Notifications go to Slack via an incoming webhook, or to Telegram via a bot. Both have a Test button. Use it — a notification channel you never tested is not a notification channel.
Full detail in the alerting docs.
You already have the server. These come with it:
Cron monitoring — append a curl to any job and get alerted when it stops reporting in:
0 3 * * * /usr/local/bin/backup.sh && curl https://logs.example.com/p/<API-KEY>/nightly-backup?state=complete
Website monitoring — uptime, response time, keyword checks and TLS expiry warnings.
Metrics — scrape any Prometheus endpoint and chart it.
Update the server:
./centrallogging-linux-amd64 -update
sudo systemctl restart centrallogging
Update an agent:
./clagent-linux-amd64 -update
sudo service clagent restart
Watch the disk. Watch that every source is still sending. An alert on “no logs from source X in an hour” catches most of what goes wrong.
Around 10GB/day you are at the edge of the design target. Storage is SQLite on one node, so there is no horizontal scale and no multi-node failover. If you need either, run Loki or ELK and budget for the operational work.
💌 Get notified on new features and updates