Analytics cookies only (Google Analytics, PostHog). No ad networks, no cross-site tracking. See our privacy policy.
Self-host TimeTagger
updated Oct 2026deployed by usprices checked · Jul 2026Install verified on Ubuntu 26.04 · Oct 2026 · how we test
We earn commissions when you shop through the links below. Full disclosure →
An interactive time tracker with a timeline you drag to record and edit entries, tags, a report view and PDF export, aimed at freelancers and individuals. Python server with a single-file data store; credentials are set with a bcrypt hash in an environment variable.
Runs on a VPS from $4/mo (Kamatera 1GB, 1 GB RAM) · prices checked Sep 2026
Our recommendation
Pick TimeTagger when you are one person (or a small group) who wants to log time by dragging on a timeline instead of filling in forms. It uses tags rather than projects, shows an interactive timeline, makes PDF and CSV reports, lets you set daily, weekly and monthly targets, offers an experimental Pomodoro timer and syncs between devices. The server is async Python with the data in SQLite, and it is GPL-3.0; the author also runs a hosted service at timetagger.app. Our snippet adapts the project's Compose example: the root-variant image pinned to a release tag, the data directory set to `/opt/_timetagger` on a named volume, and a password hash generated for you. We did not find an upstream RAM minimum, so our 128 MB floor is an estimate. Traggo is the other tag-based tracker in the catalog and Kimai the heavier option with customers, rates and invoices.
What you need
Any VPS with at least 128 MB of RAM
A domain you control — most self-hosted setups need HTTPS in front of them
TimeTagger's README and Compose examples flag these before you put it on a server:
non-negotiableOn your own machine the README says single-user mode works out of the box; for a server you provide credentials as user:bcrypt-hash pairs in TIMETAGGER_CREDENTIALS. Our snippet makes the hash with Apache's htpasswd -B in a throwaway container and prints the password once; we checked that the sign-in endpoint accepts that hash and rejects a wrong password. The Compose example warns that $ must be escaped as $$ in a Compose file, which is why the value lives in .env in single quotes.
non-negotiableThe image comes in two variants, and the upstream Compose files differ: the root variant's example keeps its data in /root/_timetagger, while the -nonroot variant runs as user 1000, needs a data directory owned by that user and uses /opt/_timetagger. Our snippet uses the root image and sets TIMETAGGER_DATADIR=/opt/_timetagger on a named volume, which matches neither example exactly (we ran it on a VM). The SQLite files live in that directory, so back the volume up.
non-negotiableThe app is served under /timetagger/: a request for / answers with a redirect there, and port 8080 is plain HTTP, so put a TLS reverse proxy in front before using it over the internet.
non-negotiableThe nonroot Compose example uses latest-nonroot and the root one an untagged image; the registry also has a tag per release, and we pin v26.1.3 (released 2026-02-02). Contributors sign a CLA and the README says the GPL-3.0 licence is meant to stop commercial reuse by others, so read it if you plan to build a service on it.