Time Tracking Made Easy: Installing Timetagger with Docker Compose

In this guide, you'll learn how to install Timetagger, an open-source time tracking tool, on your own server using Docker Compose.

Time Tracking Made Easy: Installing Timetagger with Docker Compose hero image

Introduction

In today’s working world, whether in the office or remotely, tracking work hours is often essential – be it for project billing, self-organization, or simply to keep an overview of one’s day. While there are many cloud services, some prefer full control over their data. This is where Timetagger comes in: An open-source time tracking tool with a simple, interactive web interface that you can host on your own server.

This post guides you step-by-step through the installation of Timetagger using Docker Compose. Docker simplifies the deployment of applications by packaging them along with their dependencies into containers. Docker Compose extends this by enabling the configuration and starting of multi-container applications (even though Timetagger is just one container here) in a single file. This guide is aimed at beginners but also explains the background, so you understand the ‘why’ behind the clicks.

What You Need (Prerequisites)

Before we start, make sure you have the following available:

  1. A Server: This could be a small Raspberry Pi on your home network, a virtual server from a hosting provider, or another Linux machine that runs continuously.
  2. SSH Access: You need a way to connect to your server via the command line (e.g., using Terminal/Console or a tool like PuTTY).
  3. Docker and Docker Compose: These must be installed on your server.
    • If Docker is not yet installed, follow the official documentation for your operating system: Install Docker Engine
    • Docker Compose is often included as a plugin with Docker or can be installed separately: Install Docker Compose
    • Ensure your user is allowed to run Docker commands (for example, by using sudo).

Step 1: Connect to the Server and Create Directory Structure

Open your terminal or SSH console and connect to your server:

ssh your_username@your_server_ip

Replace your_username and your_server_ip accordingly.

After successful login, we create a directory for our Timetagger project and change into it directly:

mkdir timetagger && cd timetagger

Inside this timetagger directory, we will soon create the configuration file and a subdirectory for persistent data.

Step 2: Create and Configure the compose.yml File

Docker Compose uses a YAML file (typically compose.yml or docker-compose.yml) to define the services, networks, and volumes for an application. Create this file using a text editor of your choice (e.g., nano):

nano compose.yml

Now, let’s add the content. We’ll base it on the template from the Timetagger repository (almarklein/timetagger), but adapt it slightly:

services:
    timetagger:
        image: ghcr.io/almarklein/timetagger:latest # The official Docker image for Timetagger
        container_name: timetagger # A unique name for the running container
        restart: unless-stopped # Automatically restarts the container unless manually stopped
        ports:
            - "1234:80" # Maps port 1234 on your server to port 80 inside the container
        volumes:
            - ./data:/data # Persistently stores Timetagger data in the "data" subfolder on your server
        environment:
            - TIMETAGGER_LOG_LEVEL=warn # Sets the log level (e.g., debug, info, warn, error)
            - TIMETAGGER_CREDENTIALS=your_user:YOUR_BCRYPT_HASH # Your login credentials (to be generated shortly)
            - TZ=Europe/Berlin # Sets the timezone

Explanation of the Configuration:

  • services: Defines the individual applications (only one here: timetagger).
  • image: Specifies which Docker image to use. ghcr.io/almarklein/timetagger:latest fetches the latest version from the GitHub Container Registry.
  • container_name: Gives the container a fixed name, making management easier.
  • restart: unless-stopped: An important setting for services that should always be running. The container restarts automatically, e.g., after a server reboot.
  • ports: This defines how you access Timetagger. The format is "HOST_PORT:CONTAINER_PORT". We forward requests to port 1234 on your server to port 80, where the web server inside the Timetagger container is listening. You can choose the host port (1234) freely, just ensure it’s not already in use on your server. If you use a reverse proxy (like Nginx Proxy Manager or Traefik) to access Timetagger, e.g., under a subdomain with HTTPS, you might omit this ports section entirely and add network settings for the proxy instead.
  • volumes: To ensure your tracked times and settings persist even after restarting or updating the container, the data must be stored outside the container. The format is HOST_PATH:CONTAINER_PATH. We map the /data folder inside the container to a subdirectory named data on your server (relative to the compose.yml file).
  • environment: Environment variables are set here to influence the container’s behavior.
    • TIMETAGGER_LOG_LEVEL: Controls how verbose Timetagger is in the logs. warn is a good middle ground – it shows warnings and errors, but not purely informational messages.
    • TIMETAGGER_CREDENTIALS: Your login details go here. The format is username:passwordhash. Important: Never store your password in plain text here! We will generate a secure hash shortly.
    • TZ (optional): Sets the timezone for the container, which is important for correct timestamps.

Step 3: Create the Data Directory

According to our compose.yml, Timetagger expects the data in the data subdirectory. Let’s create this now in the main timetagger directory (where compose.yml is located):

mkdir data

Your directory structure should now look like this:

timetagger/
├── compose.yml
└── data/

Step 4: Generate Credentials

Timetagger uses bcrypt for hashing passwords. This is a secure method from which the original password cannot be recovered.

  1. Open the Timetagger helper page in your browser: timetagger.app/cred

  2. Enter your desired username (e.g., admin or your name).

  3. Enter a secure password.

  4. Click “Generate”.

  5. Copy the line under “For Docker Compose (environment variable):“. It should start with your username, followed by a colon and a hash starting with $$ (e.g., admin:$$2b$$...).

    Alternative: If you prefer not to use the website, you can also generate bcrypt hashes on the command line using tools like htpasswd (from the apache2-utils package) or using Python libraries. Ensure the hash is in bcrypt format and escape the dollar signs ($) correctly.

Step 5: Insert Credentials

Open the compose.yml again with your editor:

nano compose.yml

Replace the line your_user:YOUR_BCRYPT_HASH under environment with the string you just copied. Make sure the indentation remains correct.

# ... (other parts of the file) ...
environment:
    - TIMETAGGER_LOG_LEVEL=warn
    - TIMETAGGER_CREDENTIALS=admin:$$2b$$12$$xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx # <-- Replace with your generated credentials
    - TZ=Europe/Berlin
# ... (Rest of the file) ...

Save the file and close the editor (in nano: Ctrl+X, then Y, and Enter).

Step 6: Start Timetagger

Now we are ready to start the Timetagger container. In the timetagger directory (where your compose.yml is located), execute the following command:

sudo docker compose up -d
  • sudo: Necessary if your user is not in the docker group.
  • docker compose up: Starts the services defined in compose.yml.
  • -d: Starts the containers in “detached” mode, i.e., in the background. You get your command prompt back.

Docker will now download the Timetagger image (if not already present locally) and start the container according to your configuration.

You can check the container’s status with:

sudo docker compose ps

And follow the logs live (useful for troubleshooting) with:

sudo docker compose logs -f

(Exit with Ctrl+C)

Step 7: Access and Test Timetagger

Open a web browser on your computer and enter your server’s IP address followed by the port you specified in the compose.yml (in our example, 1234):

http://your_server_ip:1234

You should see the Timetagger start page.

  1. Click on “App” and then “Login”.
  2. Log in with the username and password you used in Step 4.

If the login works – Congratulations! You have successfully installed Timetagger on your own server.

First Steps with Timetagger

Now you can start tracking your times:

  • Start Recording: Click “Record”. Enter a description of what you are doing. Use hashtags (e.g., #projectA, #meeting) to categorize entries. The timer starts running.
  • Stop/Start New Recording: Click on the running entry at the bottom to stop it. You can immediately start a new entry that follows seamlessly.
  • Adding Past Entries: Click on the timeline at the top to select past time periods and add entries manually.
  • Reports: Use the “Report” function to group and export your tracked times based on various criteria (e.g., as a PDF).
  • Views: Switch between day, week, and month views to get an overview.

Timetagger suggests previously used tags, which helps maintain consistency.

Conclusion

Installing Timetagger with Docker Compose is a manageable process that gives you full control over your time tracking data. Thanks to Docker, the setup is isolated and easy to manage. You now have a powerful yet easy-to-use tool at hand to manage your time effectively.

You can find more information and advanced configurations in the official Timetagger documentation or the GitHub repository. A good next step might be to set up a reverse proxy to access Timetagger securely via HTTPS and a custom subdomain.

Happy time tracking!

Share this post:

This website uses cookies. These are necessary for the functionality of the website. You can find more information in the privacy policy