×
root@harders-it: ~/notes
root@harders-it:~$ cat ~/notes/lumberjack.md

Lumberjack, a free open source issue tracker

2026-11-05

I needed an issue tracker for eazy.photo, something like Sentry, and I wanted an agent to look at a new error before I did. So I built Lumberjack, a free and open source issue tracker that runs on your own server. Think of it as what you get when Sentry and Grafana have a slightly too wet night out on the town.

Running it yourself is the point. eazy.photo stays away from big tech where it can, and handing every error and log line to another platform would have gone against that. With Lumberjack the data stays on a server you control.

What was missing

I run eazy.photo on my own, so its errors and logs went to a Discord channel as push messages. It was free and easy to set up. It works until you need the error from last Tuesday, or until something tips over and the messages run into a rate limit.

The health checks ran inside the application, and raised the alarm from there. An application that is down cannot tell you it is down.

Errors in the browser were hard to chase without knowing what broke and on which kind of device. And slow queries, slow requests and Web Vitals such as LCP were not easy to track without paying for a service.

What it does

Exceptions, browser errors and error logs become issues, with a history you can search.

Alerts still go to Discord if you want, or to email, Slack, Microsoft Teams, Telegram, ntfy, Pushover or a webhook. A team sets the rules once, and a project can send somewhere else. When something tips over, the same error a thousand times is one issue and one alert, an issue that keeps escalating alerts at most once every 30 minutes per channel, and a delivery that hits a rate limit is tried again. Everyone also picks what they hear themselves, by mail, in the app or as a push notification on their phone.

It measures response times, queries with N+1 hints and Web Vitals per route, down to a single trace. Jobs, scheduled tasks and commands are tracked too, so work that failed or never ran shows up.

Health checks run from Lumberjack, not from the application: HTTP, SSL, TCP, DNS and heartbeats, with outages and uptime. The alarm comes from the outside.

I also wanted the screens Grafana gives you, so they are built in: widgets for requests per minute, error rate, unresolved issues, health checks and more, on an office TV, a kiosk or a tablet. A widget can also show what Lumberjack fetches from elsewhere on an interval: a number from a JSON API, a Prometheus metric or the events of a calendar.

Like Sentry, it is built for a company with independent teams, each with their own projects.

An agent on call

An error that comes in at night rarely gets looked at within minutes. Lumberjack has an MCP server, and a project can turn on automatic triage: a GitHub Actions workflow that runs Claude Code in the repository. It runs on two triggers.

Every 15 minutes it works through the new and regressed issues. It reads their traces and context, looks for the cause in the code and writes what it found as a note on the issue. A note in Lumberjack that tags it gets an answer too.

With a repository linked to the project, a real bug with a clear cause also gets a GitHub issue, opened by the agent, or by a person with one button on the issue. Lumberjack labels those lumberjack. An issue with that label that is opened, or gets a comment, starts the agent at once, and it answers on the issue itself.

For a small fix it opens a draft pull request. It never resolves an issue and never merges.

So the morning starts with a head start instead of a cold trace, and when the agent has found the exact line, the fix is quick.

Three packages

  • Lumberjack is the server.
  • laravel-lumberjack sends a Laravel app's errors, requests, queries, jobs and logs to it.
  • lumberjack-agent is the local agent between an app and the server. The app hands it a batch and moves on, so a slow or unreachable Lumberjack never slows the app down. It runs on its own too, so an app in another language can send to it.

The server is one Docker image with the web server, Reverb, Horizon and the scheduler, and Postgres and Redis next to it in the same compose file. It needs nothing installed on the host but Docker or Podman, and one command sets it up:

curl -fsSL https://exeque.github.io/lumberjack/install.sh | sh

Built in a week

From the idea to the first release took about a week. I made the architecture and the decisions, and Claude wrote most of the implementation. As with the desktop, that speed meant a decision could be tried, looked at and changed again instead of left at good enough.

It is built for my own use, and open source on purpose, under the MIT license. Fork it and change what you like. The documentation has the rest.

# the rest are in ~/notes/