TimeTagger is a free, open source time-tracking software written in Python. It has an interactive user experience and powerful reporting.


This guide is based upon the selfhost article written by Almar Klein, the author of TimeTagger.


For this guide you should be familiar with the basic concepts of


TimeTagger is released under the GPLv3 License. All relevant information can be found in the LICENSE file in the repository of the project.


Your website domain needs to be set up:

[isabell@stardust ~]$ uberspace web domain list
[isabell@stardust ~]$


To install TimeTagger we use pip.


The pip-command defaults to pip from python 2.7. Please use a modern version of pip instead. See the manual for currently supported versions. In this guide, we use python3.9.

[isabell@stardust ~]$ pip3.9 install --user --upgrade timetagger
Collecting timetagger
 Downloading timetagger-22.6.6-py3-none-any.whl (2.9 MB)
 Successfully installed MarkupSafe-2.1.1 asgineer-0.8.1 bcrypt-3.2.2 cffi-1.15.1 click-8.1.3 h11-0.13.0 itemdb-1.1.1 jinja2-3.1.2 markdown-3.4.1 pscript-0.7.7 pycparser-2.21 pyjwt-2.4.0 timetagger-22.6.6 uvicorn-0.18.2
[isabell@stardust ~]$


Create main file

To configure TimeTagger we need to create our own main file.

[isabell@stardust ~]$ cp ~/.local/lib/python3.9/site-packages/timetagger/__main__.py ~/bin/mytimetagger.py
[isabell@stardust ~]$

Next we select the port 4800 to serve TimeTagger from. It must be mapped in the backend.

To make the application accessible from the outside, configure a web backend:

[isabell@stardust ~]$ uberspace web backend set / --http --port <port>
Set backend for / to port <port>; please make sure something is listening!
You can always check the status of your backend using "uberspace web backend list".
[isabell@stardust ~]$

First Run

We can now start the app for the first time. Therefor replace the number after the colon with the port number you chose.

Right now a user account is still missing. The app provides a dialogue to generate the encrypted string where a user is stored in.

[isabell@stardust ~]$ python3.9 ~/bin/mytimetagger.py --bind=
[INFO 2022-07-08 12:14:34] Collected 4 assets from /home/isabell/.local/lib/python3.9/site-packages/timetagger/pages/.
[INFO 2022-07-08 12:14:34] Server is starting up

Finishing installation

Now we can browse to https://isabell.uber.space/timetagger/cred to generate our preferred credentials. Choose a strong password. As a result you receive a string like isabell:$2a$08$SskWkSrYJnXvlwLPU7OAlecoCxMDs5vMr1Egs6INiqq1a4ZcH3wBa. We use this string and test the login by adding the credential to the startup script.

First stop the running python script by sending CTRL+C to the console.

[INFO 2022-07-08 12:14:34] Server is starting up
^C[INFO 2022-07-08 12:44:39] Server is shutting down
[isabell@stardust ~]$


The credentials must be encapsulated by single quotation marks.

[isabell@stardust ~]$ python3.9 ~/bin/mytimetagger.py --bind= --credentials='isabell:$2a$08$SskWkSrYJnXvlwLPU7OAlecoCxMDs5vMr1Egs6INiqq1a4ZcH3wBa'
[INFO 2022-07-08 12:46:34] Collected 4 assets from /home/isabell/.local/lib/python3.9/site-packages/timetagger/pages/.
[INFO 2022-07-08 12:46:34] Server is starting up

We should now be able to successfully login. Finally we setup a daemon to run TimeTagger automatically.

Set up the daemon

Create the file ~/etc/services.d/timetagger.ini with the following content:


Replace the port and credentials with the credentials you previously created. Also, make sure to enter the correct home directory instead of isabell.

command=python3.9 %(ENV_HOME)s/bin/mytimetagger.py --bind= --credentials='isabell:$2a$08$SskWkSrYJnXvlwLPU7OAlecoCxMDs5vMr1Egs6INiqq1a4ZcH3wBa'

This will make sure that TimeTagger is automatically started if the host reboots.

After creating the configuration, tell supervisord to refresh its configuration and start the service:

[isabell@stardust ~]$ supervisorctl reread
SERVICE: available
[isabell@stardust ~]$ supervisorctl update
SERVICE: added process group
[isabell@stardust ~]$ supervisorctl status
SERVICE                            RUNNING   pid 26020, uptime 0:03:14
[isabell@stardust ~]$

If it’s not in state RUNNING after 60 seconds, something went wrong.



Check the update feed regularly to stay informed about the newest version.

Updating is as simple as running pip again to update to the latest version and restarting the daemon.

[isabell@stardust ~]$ pip3.9 install --user --upgrade timetagger
Successfully installed timetagger-22.6.6
[isabell@stardust ~]$ supervisorctl restart timetagger
timetagger: stopped
timetagger: started
[isabell@stardust ~]$

Tested with TimeTagger 22.6.6 and Uberspace 7.13

Written by: Marvin Dickhaus <https://marvindickhaus.de>