Self-Hosting Kimai with Docker Compose

What Is Kimai?

Kimai is a free, open-source time tracking application. It handles time sheets, project tracking, customer management, invoicing, and reporting — everything a freelancer or team needs to track billable hours. It replaces Toggl, Harvest, and Clockify with a self-hosted solution you fully control. Official site

Prerequisites

  • A Linux server (Ubuntu 22.04+ recommended)
  • Docker and Docker Compose installed (guide)
  • 1 GB of free RAM
  • A domain name (recommended for HTTPS access)

Docker Compose Configuration

services:
  kimai-db:
    image: mysql:8.3
    container_name: kimai-db
    environment:
      MYSQL_DATABASE: kimai
      MYSQL_USER: kimai
      MYSQL_PASSWORD: change-this-database-password
      MYSQL_ROOT_PASSWORD: change-this-root-password
    volumes:
      - kimai-db:/var/lib/mysql
    networks:
      - kimai
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
      interval: 10s
      timeout: 5s
      retries: 5

  kimai:
    image: kimai/kimai2:apache-2.51.0
    container_name: kimai
    ports:
      - "8001:8001"
    environment:
      # Admin account (created on first run)
      ADMINMAIL: [email protected]
      ADMINPASS: change-this-admin-password  # CHANGE THIS
      # Database connection
      DATABASE_URL: mysql://kimai:change-this-database-password@kimai-db/kimai?charset=utf8mb4&serverVersion=8.3.0
      # Application settings
      TRUSTED_PROXIES: "0.0.0.0/0"   # Set to reverse proxy IP in production
      TRUSTED_HOSTS: "localhost,kimai.example.com"
    volumes:
      - kimai-data:/opt/kimai/var/data
      - kimai-plugins:/opt/kimai/var/plugins
    networks:
      - kimai
    depends_on:
      kimai-db:
        condition: service_healthy
    restart: unless-stopped

networks:
  kimai:

volumes:
  kimai-db:
  kimai-data:
  kimai-plugins:

Start Kimai:

docker compose up -d

First startup takes 1-2 minutes for database migration. Access the web UI at http://your-server:8001 and log in with the admin credentials you set.

Initial Setup

After first login:

  1. Create customers — navigate to Admin → Customers. Each customer represents a client you bill.
  2. Create projects — under each customer, create projects. Projects organize work streams.
  3. Create activities — activities describe the type of work (development, design, meetings). They can be global or project-specific.
  4. Create team members — Admin → Users. Assign roles: User, Teamlead, Admin, or Super Admin.
  5. Start tracking — click the green play button to start a timer, or manually add time entries.

Features at a Glance

FeatureDetails
Time trackingStart/stop timer, manual entry, calendar view
Projects & customersHierarchical organization
TeamsAssign members to projects, team-based reporting
InvoicingGenerate invoices from tracked time, multiple templates
ReportingDaily, weekly, monthly reports with filtering
ExportCSV, PDF, XLSX, HTML exports
APIFull REST API for integrations
PluginsMarketplace with 50+ plugins (expenses, vacation, approvals)
2FATOTP-based two-factor authentication
LDAP/SAMLEnterprise authentication support

Configuration

Timezone

Set the application timezone via environment variable:

environment:
  APP_TIMEZONE: America/New_York

Memory Limit

For larger teams (20+ users), increase PHP memory:

environment:
  memory_limit: 512M

Email Notifications

Configure SMTP for invoice delivery and password resets:

environment:
  MAILER_URL: smtp://mail.example.com:587?encryption=tls&[email protected]&password=mail-password
  MAILER_FROM: [email protected]

Invoicing

Kimai generates invoices directly from tracked time entries:

  1. Go to Invoices → select customer, date range, and entries
  2. Choose a template (built-in or custom DOCX/XLSX/PDF)
  3. Generate and download the invoice
  4. Entries are marked as invoiced to prevent double-billing

Custom invoice templates use Twig syntax — upload them to the var/invoices/ directory inside the container.

Reverse Proxy

Behind Nginx Proxy Manager:

Proxy Host: time.example.com → http://kimai:8001

Set TRUSTED_PROXIES and TRUSTED_HOSTS in your environment to match your proxy setup. Without this, Kimai may generate incorrect URLs.

Backup

Critical data to back up:

VolumeContains
kimai-dbAll time entries, customers, projects, users
kimai-dataFile uploads, custom templates
kimai-pluginsInstalled plugins
# Database dump (preferred)
docker exec kimai-db mysqldump -u kimai -p'change-this-database-password' kimai > kimai-backup-$(date +%Y%m%d).sql

See Backup Strategy for automated approaches.

Troubleshooting

Login fails after first setup

Symptom: Admin credentials don’t work at the login page. Fix: Database migration may not have completed. Check logs: docker logs kimai. If you see migration errors, ensure MySQL is healthy and restart: docker compose restart kimai.

”Trusted proxy” warnings in logs

Symptom: Kimai logs show “request not trusted” or URLs use HTTP instead of HTTPS. Fix: Set TRUSTED_PROXIES to your reverse proxy IP or 0.0.0.0/0 (for Docker networks). Also set TRUSTED_HOSTS to your domain.

Slow performance with large datasets

Symptom: Reports and invoice generation slow down with 10,000+ entries. Fix: Increase PHP memory_limit to 512M or 1G. Ensure MySQL has adequate innodb_buffer_pool_size (default may be too low).

Plugin installation fails

Symptom: Error when installing plugins from the marketplace. Fix: Ensure the kimai-plugins volume is writable. Inside the container: docker exec kimai ls -la /opt/kimai/var/plugins/. Fix permissions if needed.

Resource Requirements

  • RAM: ~200 MB idle (Kimai + MySQL), ~500 MB under load with 10+ concurrent users
  • CPU: Low — PHP application with periodic report generation
  • Disk: ~500 MB for application + database. Grows with file uploads.

Verdict

Kimai is the best self-hosted time tracker for freelancers and small teams. The invoicing integration sets it apart — track time and bill clients from the same tool. For enterprise teams needing approval workflows and advanced reporting, the plugin marketplace fills the gaps. If you need simpler time tracking without project management, look at Traggo as a lighter alternative.

Comments