Haby is a self-hosted habit and goal tracker built for private, homelab-friendly deployments. It combines daily habits, progress goals, lightweight widgets, and a clean dashboard into a single containerized app.
- Multi-user authentication with an admin-managed user list
- Default first-run account with forced password change
- Separate habit and goal cards
- Optional mini calendar and mini chart on each card
- Line, column, and pie card charts
- Right-side widgets for overall history, today list, and calendar views
- Card archiving and archived section support
- Import preview before full import
- Local SQLite persistence in a single
/datavolume - Docker-first deployment with a production example compose file
The initial first-run account is:
- Username:
Haby - Password:
Haby
You are prompted to change the password after the first login.
Haby seeds a curated default dashboard for first-time use and for new users:
Habit cards
- 5 active habit cards.
- Mixed card layouts with mini calendars, compact cards, repeatable cards, and different visual styles.
- Charts are widget-only, so habit cards stay focused on daily tracking.
Goal cards
- 4 active goal cards.
- Goal examples include steps, distance, sleep, and reading progress.
- Goal cards use progress bars, units, mini calendars, and compact layouts.
Archive
- 2 archived sample cards.
- The archive section is visible immediately on first run.
Widgets
- Calendar
- Today List
- Overall History
- Goal/card chart widget example
- Frontend: React + Vite + TypeScript
- Backend: Express + TypeScript
- Database: SQLite
- Container: Multi-stage Docker build
.
├── app/
│ ├── client/ # React frontend
│ └── server/ # Express backend
├── compose.yaml.example # Example Docker Compose file
├── Dockerfile # Production multi-stage image
├── .env.example # Optional runtime environment example
├── SECURITY.md # Security policy and hardening notes
└── docs/
└── screenshots/ # README screenshots
npm install --prefix app
npm install --prefix app/client
npm install --prefix app/server
npm run dev --prefix app/server
npm run dev --prefix app/clientPull the latest image from Docker Hub:
docker pull zvijer1987/haby:latestA commented production example is included in compose.yaml.example.
Quick start:
cp compose.yaml.example compose.yaml
mkdir -p data
docker compose up -dHaby stores persistent runtime data in /data inside the container. The mounted directory contains:
- the SQLite database
- uploaded profile pictures
- user settings and persisted application state
- Export downloads a dated JSON backup file
- Import runs a preview first
- Import can restore habits, goals, archived cards, entries, categories, and settings
- Change the default password immediately after the first login
- Do not expose Haby directly to the public internet without an authenticated reverse proxy
- Run behind HTTPS when used outside a trusted LAN
- Keep the
/datavolume private and backed up - Review
SECURITY.mdbefore publishing or opening access
See CONTRIBUTING.md for repository conventions and contribution notes.
The container now runs as the standard Node.js user:
- UID: 1000
- GID: 1000
This is better for most self-hosted bind mount setups where the mounted data folder is owned by the normal host user.
Existing users who update from an older image may need to fix ownership of their mounted /data folder if they see this SQLite error:
SqliteError: attempt to write a readonly database
For bind-mounted data folders, run:
sudo docker stop haby
sudo chown -R 1000:1000 /path/to/haby/data
sudo chmod -R u+rwX,g+rwX /path/to/haby/data
sudo docker start haby
Example for a local ./data folder:
sudo docker stop haby
sudo chown -R 1000:1000 ./data
sudo chmod -R u+rwX,g+rwX ./data
sudo docker start haby
New installations using a normal user-owned bind mount should work without extra permission changes.