Self-hosted service
daya0576/beaverhabits avatar
daya0576/beaverhabits

Beaver Habit Tracker: a self-hosted streak grid with no goals and two storage backends

A self-hosted habit tracking app without "Goals"

1,836 stars79 forksPythonBSD-3-Clause

At a glance

What is it?
Beaver Habit Tracker is a Python habit tracker that deliberately omits goal targets and runs from a single container. The decision worth weighing is HABITS_STORAGE: a SQLite file or a JSON file on the mounted volume.
Who is it for?
Adopt Beaver Habit Tracker if you want a habit grid on your own hardware, you are comfortable mounting a host directory with matching UID ownership, and you do not need goal targets or multi-user accounts. Do not adopt it if you need per-user isolation, since TRUSTED_LOCAL_EMAIL skips authentication entirely, or if you want a data model that already carries dates for future entries.
Can I use it commercially?
Yes. BSD-3-Clause is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 38 days ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

The missing feature is the product: habits without goal targets

The repository description is blunt: a self-hosted habit tracking app without "Goals". Most trackers ask you to declare a target first, such as five sessions a week or thirty minutes a day, and then measure you against it. Beaver Habit Tracker drops that layer. What remains is the checkmark and the streak, which is the part of habit tracking that people actually look at daily. The README credits two inspirations: the Android app Loop Habit Tracker by @iSoron, and a NiceGUI todo list example by @zauberzeug. The second credit is the honest one, because it tells you the interface is built on NiceGUI rather than a separate JavaScript front end. The intended user is someone who already runs a container host and wants a private grid of habits rather than another account on someone else's service. The README also points at a hosted option at beaverhabits.com with a demo and pricing plans, so the project is not self-hosting-only. The self-hosted path is the one with the environment variables and the volume mount, and it is the path this article covers.

How the storage mode changes what you are actually running

The most consequential configuration choice is HABITS_STORAGE, and the README states both options plainly. DATABASE stores habits in a single SQLite database named habits.db. USER_DISK saves them in a local JSON file. That is not a cosmetic difference. SQLite gives you a file you can query with the sqlite3 command line and back up with a file copy while the process is stopped. A JSON file is easier to read and diff, and easier to hand-edit, but it is also easier to corrupt with a partial write or a bad manual edit. The README does not describe a migration path between the two modes, so treat the choice as something to make before you accumulate history. The container is the other half of the architecture. The README notes the container starts as nobody to increase security and to stay OpenShift compatible, which is why the run command passes -u $(id -u):$(id -g) and why the Compose example sets user: 1000:1000. The README links a discussion thread about permission issues and states the fix directly: ensure the UID owning the host folder aligns with the UID of the user inside the container. If those two numbers disagree, the app cannot write its storage file, and the failure will look like data not saving rather than a permissions error.

Getting it running: the docker run line and the Compose keys

The README gives a single-container command. It runs daya0576/beaverhabits:latest, names the container beaverhabits, passes the current user and group IDs with -u $(id -u):$(id -g), sets HABITS_STORAGE=USER_DISK, mounts ./beaver/ to /app/.user/, and publishes port 8080. The Compose example is the same shape with more keys exposed. It sets container_name, user: 1000:1000, and an environment block containing HABITS_STORAGE, TRUSTED_LOCAL_EMAIL, INDEX_HABIT_DATE_COLUMNS, and ENABLE_IOS_STANDALONE. TRUSTED_LOCAL_EMAIL takes an email address and, per the inline comment in the Compose file, skips authentication. INDEX_HABIT_DATE_COLUMNS is set to 5 in the example and controls how many date columns appear on the index page. ENABLE_IOS_STANDALONE is set to true. The Compose file comments point to a wiki page titled Environment variables for the full list, which is where you should look before assuming the four shown are exhaustive. The volume line mounts ./beaver/ to /app/.user/, and the comment tells you to change the directory to match your own file scheme. Unraid users get a separate path: the README says to search for "Beaver Habit Tracker" in the Community Apps store. For development, the README favors uv: run uv venv && uv sync to create the environment and install dependencies, then ./start.sh dev to start the server.

Authentication is a switch you flip, not a feature you configure

TRUSTED_LOCAL_EMAIL is the sharpest edge in the setup. The Compose example describes it as skipping authentication, and it takes a single email address. That is a reasonable design for a container bound to a home network or reached over a VPN, where the person hitting port 8080 is the person who owns the machine. It is the wrong design the moment the port is exposed to the internet or shared with other people, because there is no visible notion in the supplied material of separate accounts with separate data. The README does not describe a multi-user model, a password reset flow, or an admin role. If you need several people tracking their own habits with their own logins, the material here gives you nothing to configure, and the honest reading is that this is a single-user application with an optional authentication bypass. The same caution applies to the hosted service: the README advertises it as zero configuration with high availability, but the self-hosted environment variables and the hosted product are not documented as interchangeable, so do not assume a self-hosted config maps onto a plan.

Where the project stops and the derivatives begin

The README has a Derivatives section that is more informative than most feature lists, because it shows what the core does not do. There is a wiki page titled Beaver Habit Tracker API How-to Guide, and around it sit third-party or community integrations: HabitDeck, which turns a Stream Deck into an interactive habit tracker; an Apple Shortcut for sharing the app on iPhone; a Home Assistant switch for marking a habit done; a CalDAV bridge that runs a calDAV server hosting the habits as tasks; and an iOS native app described as an offline-first client. Read that list as a map of gaps. Calendar integration is not in the core, it is a bridge. Native mobile is not in the core, it is a separate client. Home automation is not in the core, it is a switch built on the API. The core is the web grid plus storage plus the API the wiki documents. That is a clean separation, and it means the project's surface area stays small. It also means that if you want any of those integrations, you are depending on a wiki page, a discussion thread, or a repository maintained by someone else, with its own release cadence and its own compatibility risk against the API.

The alternative is a general-purpose tracker, and the difference is the data model

The obvious alternative is a general-purpose self-hosted tracker that does carry goals, targets and richer statistics. The difference is not the checkbox. It is what the record means. In a goal-oriented tracker, a logged entry is evaluated against a threshold, and the interface is built to show progress toward that threshold. In Beaver Habit Tracker, based on the repository description and the README, the entry is the record and the streak is the summary. There is no threshold to miss. The trade-off runs both ways. You lose the ability to say "I want to run three times a week" and see a percentage, and you gain an interface where every day is either marked or not, with no configuration between you and the grid. INDEX_HABIT_DATE_COLUMNS is the only knob the README shows for how much of that grid is visible at once, and it is a display setting, not a goal setting. If your tracking habit depends on seeing a completion rate, this project is the wrong tool and you will spend your time working around the missing layer rather than using the app. If the streak itself is the motivator, the omission is the reason to pick it.

Maintenance, releases and the BSD-3-Clause terms

The project is not archived, the default branch is main, and the last push recorded is 2026-08-09. The release history shows v0.10.0 on 2026-07-26, v0.9.1 on 2026-05-20, and v0.9.0 on 2026-02-20. That is a steady cadence of roughly two to three months between minor releases, and the version numbers are still below 1.0, which is the project's own signal that interfaces and configuration may move. The README does not state a database schema version, a migration command, or a documented upgrade procedure, so the practical upgrade approach visible in the material is to pull a new image tag and restart the container, with a copy of the mounted volume taken first. The Docker image is published as daya0576/beaverhabits:latest in the examples, and pinning to a version tag instead is a choice the README does not discuss but the release list makes possible. The licence is BSD-3-Clause, a permissive licence that generally allows use, modification and redistribution provided the copyright notice and licence text are retained. That is a summary of the licence family, not legal advice; read the LICENSE file in the repository and the terms of the hosted service separately, since the README presents beaverhabits.com as a commercial product with its own pricing page.

Editorial conclusion

Adopt Beaver Habit Tracker if you want a habit grid on your own hardware, you are comfortable mounting a host directory with matching UID ownership, and you do not need goal targets or multi-user accounts. Do not adopt it if you need per-user isolation, since TRUSTED_LOCAL_EMAIL skips authentication entirely, or if you want a data model that already carries dates for future entries. Before committing, decide between HABITS_STORAGE=DATABASE and HABITS_STORAGE=USER_DISK, check the wiki's environment variable list against your Compose file, and confirm that the UID in your user: line matches the owner of the mounted folder.

Official sources

  1. daya0576/beaverhabits on GitHub
  2. License: BSD-3-Clause
  3. Project website
  4. README
  5. Releases
Community notes

Community notes