Beaver Habit Tracker: a self-hosted habit tracker without goals
A self-hosted habit tracking app without "Goals"
At a glance
- What is it?
- Beaver Habit Tracker is a Python and NiceGUI app for marking habits done, not for scoring them. Here is how the Docker install works, what HABITS_STORAGE changes, and where the no-goals model breaks down.
- Who is it for?
- Adopt Beaver Habit Tracker if you want a habit log you own, can reach from a browser or an iOS client, and are willing to run a container with a mounted volume. Skip it if your habit practice depends on targets, reminders, or a hosted service you never have to patch.
- 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 13 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 29, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What Beaver Habit Tracker is for
The project describes itself in one line: a self-hosted habit tracking app without "Goals". That phrase is the design position. Most habit apps ask you to define a target (three times a week, twenty minutes a day) and then judge each check-in against it. Beaver Habit Tracker records whether a habit was done on a date and shows the resulting streaks. There is no target field to configure.
The audience follows from that. It suits people who already know what they want to do and only need a place to record it, and who would rather run the software themselves than hand their daily log to a vendor. The README points at a hosted option at beaverhabits.com as well, with a demo instance, so the self-hosted path is one of two, not the only one.
The README credits two inspirations: the Android app Loop Habit Tracker and a NiceGUI todo list example. Both are telling. The first is a well-known offline habit app, the second explains the stack choice. Beaver Habit Tracker is closer to a web-shaped Loop than to a goal-setting coach.
How the app is put together
The stack is visible in pyproject.toml. The UI layer is NiceGUI, which is a Python framework that renders server-side components into a browser page; the web server is uvicorn, with uvicorn-worker for running multiple processes. Authentication and user records come from fastapi-users with the SQLAlchemy adapter. Persistence is SQLAlchemy 2.x over either aiosqlite or asyncpg. That means the same code path talks to SQLite or PostgreSQL depending on configuration, and the README's HABITS_STORAGE variable is the switch.
Two storage modes are named in the README. HABITS_STORAGE=DATABASE keeps everything in a single SQLite file called habits.db. HABITS_STORAGE=USER_DISK writes to a local JSON file instead. The Docker examples mount a host directory at /app/.user/, which is where the user data lives in the USER_DISK case. This is a small but real decision: a single database file is easier to back up and query, while a JSON file per user is easier to read and hand-edit. The README does not argue for either, it just exposes both.
Other environment variables appear in the compose example: TRUSTED_LOCAL_EMAIL skips authentication for a given address, INDEX_HABIT_DATE_COLUMNS changes how many date columns the index page shows, and ENABLE_IOS_STANDALONE turns on standalone mode for the iOS client. The compose file itself points to a wiki page for the full list rather than enumerating it, which is the honest place to look when a variable is missing from the README.
The repository also carries fly.toml, a healthcheck.py at the top level, and a docker/ directory, so the image build and the hosted deployment share the same codebase. The .gitmodules entry suggests at least one vendored dependency, though the README does not say which.
Installing Beaver Habit Tracker with Docker
The README gives a one-line Docker command as the fastest path. It runs the published image, maps port 8080, sets the storage mode to USER_DISK, and mounts a local beaver/ folder into the container at /app/.user/. The -u flag passes your own user and group IDs so files written into the mount are owned by you rather than by root.
docker run -d --name beaverhabits \
-u $(id -u):$(id -g) \
-e HABITS_STORAGE=USER_DISK \
-v ./beaver/:/app/.user/ \
-p 8080:8080 \
daya0576/beaverhabits:latestAfter the container starts, open http://localhost:8080 in a browser. You should see the habit index page. If the page loads but the container logs permission errors on the mounted folder, the UID inside the container does not match the owner of ./beaver/; the README calls this out directly and links to a discussion thread about it.
For a longer-lived setup, the README provides a Compose file. It adds restart behaviour, pins the user to 1000:1000, sets TRUSTED_LOCAL_EMAIL to skip the login step, and shows the two variables that change the interface: INDEX_HABIT_DATE_COLUMNS and ENABLE_IOS_STANDALONE.
services:
beaverhabits:
container_name: beaverhabits
user: 1000:1000
environment:
- HABITS_STORAGE=USER_DISK
- [email protected]
- INDEX_HABIT_DATE_COLUMNS=5
- ENABLE_IOS_STANDALONE=true
volumes:
- ./beaver/:/app/.user/
ports:
- 8080:8080
restart: unless-stopped
image: daya0576/beaverhabits:latestOn Unraid, the README says the app is in the Community Apps store under the name "Beaver Habit Tracker", which avoids writing any of this by hand. For development rather than deployment, the README uses uv: run uv venv && uv sync to create the environment and install dependencies, then ./start.sh dev to launch the server.
uv venv && uv sync
./start.sh devThe first real use after install is unglamorous: create a habit, then tap today's cell. There is no target to set, so the only configuration is the name.
The no-goals model is the main limitation
Removing goals removes a whole category of feedback. There is no completion percentage, no weekly quota, no alert when you fall behind. If your reason for tracking is to be pushed, this app will not push you. It shows what happened; it does not tell you what should have happened.
The README also does not document notifications or reminders. For a habit tracker that is a notable gap, and it is consistent with the stated position rather than an oversight to work around. A user who needs a nudge at 21:00 should look elsewhere or build the nudge themselves against the API.
The API is the escape hatch. The README links to a wiki page titled "Beaver Habit Tracker API How-to Guide", and the derivatives section shows what people have built on it: a Stream Deck plugin called HabitDeck, an Apple Shortcut for iPhone, a Home Assistant switch that marks a habit done, and a CalDAV bridge that exposes habits as tasks. Those integrations exist because the core app stays narrow.
Storage is the second constraint. HABITS_STORAGE=USER_DISK writes JSON per user, which is fine for one person and awkward for a household or a team, since there is no shared view described in the README. HABITS_STORAGE=DATABASE consolidates into habits.db, but the README does not describe multi-user administration, roles, or how a second account is created. It also does not document rollback or downgrade steps, so pinning a version tag rather than :latest is the conservative choice when you care about being able to return to a known state.
Beaver Habit Tracker compared with Habitica and Loop
Habitica is the obvious alternative for anyone who wants the goal machinery Beaver Habit Tracker deliberately omits. Habitica turns habits into a role-playing game with rewards, penalties and social accountability. The difference is not cosmetic: Habitica's model assumes it can motivate you through consequences, while Beaver Habit Tracker assumes you will show up on your own and only need a record. If the game layer is what keeps you consistent, Beaver's restraint will feel like a missing feature.
Loop Habit Tracker, which the README names as an inspiration, is an Android app with local storage and a strong streak-and-frequency view. Its model includes frequency targets, which Beaver does not. The trade is platform: Loop lives on a phone, Beaver lives in a browser you host, with an iOS native client available through the project wiki and an Apple Shortcut for sharing the app on iPhone. If you want an offline-first phone app and nothing to run, Loop is the shorter path.
Against a hosted service, the difference is custody. Beaver Habit Tracker's self-hosted mode keeps habits.db or the JSON files on a volume you control, and the README's Docker examples are built around that mount. The cost is that you are the operator: image updates, volume permissions and backups are yours. The project also offers a cloud service at beaverhabits.com with a demo instance, which is the honest answer for someone who wants the interface without the container.
Maintenance, licence and upgrade cost
The repository is not archived, and the last push was on 2026-08-09. Releases are irregular rather than monthly: v0.9.0 in February 2026, v0.9.1 in May 2026, v0.10.0 in July 2026. That cadence matters if you depend on a fix landing quickly; it also means :latest can move under you between deployments, so pinning a tag is the safer default.
The licence is BSD-3-Clause, which is permissive and permits commercial use and modification provided the copyright notice and disclaimer are retained. It does not impose a copyleft obligation on your own code. This is a summary of the identifier, not legal advice; read LICENSE in the repository if the distinction matters to your organisation.
Upgrade cost is mostly volume ownership. The container starts as nobody, and the README warns that the UID owning the host folder must match the UID inside the container to avoid permission issues. A redeploy that changes the user mapping, or a host migration that changes file ownership, is the most likely way to break a working install. Back up the mounted folder before pulling a new image, and note that the README does not document a rollback procedure if a new version misbehaves.
Editorial conclusion
Adopt Beaver Habit Tracker if you want a habit log you own, can reach from a browser or an iOS client, and are willing to run a container with a mounted volume. Skip it if your habit practice depends on targets, reminders, or a hosted service you never have to patch. Before committing, verify that the UID inside the container matches the owner of the mounted folder, decide between HABITS_STORAGE=DATABASE and HABITS_STORAGE=USER_DISK, and check the environment variable list in the project wiki, since the README points there rather than listing them itself.
Frequently asked questions
What is the best free habit tracker app?
Beaver Habit Tracker is free to self-host under BSD-3-Clause and runs from a Docker image on port 8080. The project also offers a paid cloud service at beaverhabits.com, so the self-hosted route is the no-cost one.
What is the best app to keep track of my daily routine?
Beaver Habit Tracker records daily check-ins and shows streaks rather than setting targets, so it fits a routine you already follow. It is reachable from a browser, and the README lists an iOS native client and an Apple Shortcut as derivatives.
Is the habit app worth it?
That depends on whether you want goal tracking, which Beaver Habit Tracker deliberately omits. Its value is custody of the data: with HABITS_STORAGE=USER_DISK the habits are JSON files in a folder you mount, and with HABITS_STORAGE=DATABASE they are in a single habits.db file.
What is the best app to track bad habits?
Beaver Habit Tracker does not separate good habits from bad ones; it records whether a habit was done on a date and shows the streak. The README describes it as a habit tracking app without "Goals", so there is no scoring or penalty layer for a habit you are trying to quit.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/daya0576-beaverhabits)