Guide de déploiement

Héberger Kimai sur un VPS : time tracking open source

Déployer sur un VPS Cloud →

Tutoriel

Héberger Kimai sur un VPS : time tracking open source

Self-hosting14 min de lecture14 étapes

Kimai est un logiciel de suivi du temps open source, sous licence MIT, capable de remplacer Toggl Track, Clockify ou Harvest sur la durée : chronomètre, feuilles de temps, clients, projets, activités, taux horaires, budgets, rapports et facturation. Ce guide va au-delà de l'installation. Il détaille l'architecture de la pile Docker, un `docker-compose.yml` annoté pour qui déploie à la main, la mise en HTTPS derrière un reverse proxy, la création des comptes en ligne de commande, le modèle de données et les rôles, la facturation, l'API REST, les plugins, la sauvegarde, les mises à jour et les erreurs les plus fréquentes. Vous saurez ensuite exploiter Kimai en production pour une équipe, pas seulement le faire démarrer.

Sommaire· Pourquoi self-hoster Kimai ?1/21
  1. 01Pourquoi self-hoster Kimai ?
  2. 02Architecture : ce qui tourne sur le VPS
  3. 03Les briques de la pile
  4. 04Déployer Kimai sur ServOrbit
  5. 05Installation manuelle avec Docker Compose
  6. 06Variables d'environnement à connaître
  7. 07Mettre Kimai derrière un domaine en HTTPS
  8. 08Créer des utilisateurs en ligne de commande
  9. 09Le modèle de données : clients, projets, activités
  10. 10Taux et budgets
  11. 11Rôles, équipes et permissions
  12. 12Facturer à partir des feuilles de temps
  13. 13Préparer votre premier modèle de facture
  14. 14TVA et mentions obligatoires
  15. 15API REST et intégrations
  16. 16Étendre Kimai avec des plugins
  17. 17Sauvegarde et restauration
  18. 18Mises à jour sans surprise
  19. 19Dépannage courant
  20. 20Kimai face à Toggl Track, Clockify et Harvest
  21. 21Dimensionner le VPS

Pourquoi self-hoster Kimai ?

Un outil de suivi du temps concentre des données sensibles : qui travaille pour quel client, combien d'heures, à quel taux. Sur un service SaaS, ces informations vivent chez l'éditeur et le coût augmente avec le nombre de comptes. En hébergeant Kimai sur votre propre VPS, vous gardez la base de données sous la main, vous ajoutez des utilisateurs sans frais de licence et vous choisissez vous-même le rythme des mises à jour.

  • Licence MIT — aucun frais de licence, aucune limite d'utilisateurs imposée par l'éditeur.
  • Facturation intégrée — les factures se génèrent directement depuis les feuilles de temps, sans module externe.
  • API REST documentée — branchez vos outils internes (tickets, RH, tableaux de bord) sur vos propres données.
  • Souveraineté des données — heures, taux et fiches clients restent dans votre base MySQL.
  • Pile légère — un conteneur applicatif et une base MySQL, à l'aise sur un VPS d'entrée de gamme.

Architecture : ce qui tourne sur le VPS

Kimai est une application PHP construite sur le framework Symfony. La version 2 s'appuie sur MySQL ou MariaDB ; SQLite n'est plus pris en charge. L'image officielle kimai/kimai2 existe en deux variantes : apache (serveur web intégré, écoute sur le port 8001) et fpm (à placer derrière votre propre Nginx). Le template ServOrbit utilise kimai/kimai2:apache-latest avec MySQL 8.0, ce qui ramène la pile à deux conteneurs.

Les briques de la pile

  • Conteneur kimai — Apache et PHP, l'application Symfony dans /opt/kimai, port 8001 publié uniquement sur 127.0.0.1.
  • Conteneur db — MySQL 8.0 avec un healthcheck mysqladmin ping : Kimai ne démarre qu'une fois la base prête.
  • Volume kimai_db — les fichiers de données MySQL, c'est-à-dire toutes vos feuilles de temps.
  • Volume kimai_data — /opt/kimai/var/data, les fichiers déposés dans l'application (modèles de facture, documents).
  • Volume kimai_public — /opt/kimai/public/avatars, les avatars des utilisateurs.
  • Reverse proxy — Nginx, Caddy ou Traefik termine le HTTPS et transmet les requêtes au port local 8001.

Déployer Kimai sur ServOrbit

Le Marketplace ServOrbit provisionne la pile complète sur Ubuntu 24.04 : Docker, MySQL 8.0, le conteneur Kimai, les trois volumes et un mot de passe administrateur généré. Aucun nom de domaine n'est nécessaire pour commencer.

  1. Lancer le déploiement

    Dans votre espace client : Marketplace → ERP & Gestion → Kimai → Déployer. ServOrbit crée le VPS, installe Docker et lance la pile (MySQL 8 + Apache/PHP) automatiquement.

  2. Récupérer les identifiants

    Attendez environ 60 secondes. La carte de l'app affiche vos identifiants : login [email protected], mot de passe généré.

  3. Se connecter sans domaine

    Ouvrez un tunnel SSH : ssh -L 8080:127.0.0.1:8001 root@<ip> puis http://localhost:8080. Ajoutez un domaine depuis le tableau de bord quand vous êtes prêt.

  4. Créer client et projet

    Créez votre premier client, puis un projet lié à ce client, et au moins une activité. Fixez un taux horaire ou un budget.

  5. Saisir les premières heures

    Cliquez ▶ pour lancer le chronomètre, choisissez le projet et l'activité : Kimai enregistre vos heures en temps réel.

Dès la première connexion, ouvrez votre profil pour remplacer l'adresse [email protected] par une adresse réelle et changer le mot de passe généré. Conservez ensuite ce compte super-administrateur pour l'administration et créez des comptes nominatifs pour le travail quotidien.

Installation manuelle avec Docker Compose

Si vous préférez installer Kimai vous-même sur un VPS existant, voici un docker-compose.yml équivalent au template, avec un volume de plus pour les plugins. Placez-le dans un dossier dédié, par exemple /opt/kimai.

services:
  db:
    image: mysql:8.0
    restart: unless-stopped
    environment:
      MYSQL_DATABASE: kimai
      MYSQL_USER: kimai
      MYSQL_PASSWORD: ${DB_PASSWORD}
      MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}
    volumes:
      - kimai_db:/var/lib/mysql
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "127.0.0.1", "--silent"]
      interval: 10s
      retries: 12

  kimai:
    image: kimai/kimai2:apache-latest
    restart: unless-stopped
    depends_on:
      db:
        condition: service_healthy
    ports:
      - "127.0.0.1:8001:8001"
    environment:
      DATABASE_URL: "mysql://kimai:${DB_PASSWORD}@db/kimai?charset=utf8mb4&serverVersion=8.0.34"
      APP_SECRET: ${APP_SECRET}
      ADMINMAIL: [email protected]
      ADMINPASS: ${ADMIN_PASSWORD}
      TRUSTED_HOSTS: "localhost,127.0.0.1,kimai.votre-domaine.com"
    volumes:
      - kimai_data:/opt/kimai/var/data
      - kimai_plugins:/opt/kimai/var/plugins
      - kimai_public:/opt/kimai/public/avatars

volumes:
  kimai_db:
  kimai_data:
  kimai_plugins:
  kimai_public:

Générez ensuite les secrets dans un fichier .env lu automatiquement par Compose, puis démarrez la pile. Au premier lancement, le conteneur crée le schéma de base et le compte administrateur défini par ADMINMAIL et ADMINPASS.

cat > .env <<EOF
DB_PASSWORD=$(openssl rand -hex 16)
DB_ROOT_PASSWORD=$(openssl rand -hex 16)
APP_SECRET=$(openssl rand -hex 32)
ADMIN_PASSWORD=$(openssl rand -hex 12)
EOF
chmod 600 .env
docker compose up -d
docker compose logs -f kimai

Variables d'environnement à connaître

  • DATABASE_URL — chaîne de connexion Doctrine : utilisateur, mot de passe, hôte db, nom de base, charset=utf8mb4 et serverVersion. Le mot de passe étant dans une URL, évitez les caractères @, / ou : ; un secret hexadécimal règle la question.
  • APP_SECRET — clé Symfony utilisée pour signer sessions et jetons. Une valeur aléatoire longue, générée une fois et jamais modifiée sans raison : la changer déconnecte tout le monde.
  • ADMINMAIL et ADMINPASS — compte super-administrateur créé au premier démarrage. Une fois l'instance en place, gérez les comptes depuis l'interface ou la console.
  • TRUSTED_HOSTS — liste des noms d'hôte acceptés, séparés par des virgules. Elle doit contenir votre domaine public, sinon Symfony refuse les requêtes.
  • MAILER_URL — transport d'e-mail. Le template ServOrbit le fixe à null://localhost : aucun mail n'est envoyé. Renseignez un serveur SMTP pour activer la réinitialisation de mot de passe et les notifications.

Mettre Kimai derrière un domaine en HTTPS

  1. Pointer le DNS

    Créez un enregistrement A kimai.votre-domaine.com vers l'IP publique du VPS et vérifiez la propagation avec dig +short kimai.votre-domaine.com.

  2. Configurer le reverse proxy

    Le port 8001 n'écoute que sur 127.0.0.1 : seul le proxy local peut l'atteindre. Exemple de bloc Nginx :

    server {
        listen 80;
        server_name kimai.votre-domaine.com;
    
        location / {
            proxy_pass http://127.0.0.1:8001;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
        }
    }
  3. Obtenir le certificat

    Avec certbot et son plugin Nginx, le certificat Let's Encrypt est émis et le bloc server est complété pour le port 443 :

    apt install -y certbot python3-certbot-nginx
    certbot --nginx -d kimai.votre-domaine.com
  4. Déclarer le domaine à Kimai

    Ajoutez kimai.votre-domaine.com à TRUSTED_HOSTS, puis docker compose up -d pour recréer le conteneur. Si les liens générés restent en http://, consultez la documentation Kimai sur les reverse proxies : les en-têtes X-Forwarded-* ne sont pris en compte que depuis un proxy déclaré de confiance.

  5. Fermer les accès inutiles

    Dans le pare-feu, n'ouvrez que 22, 80 et 443. MySQL n'a aucun port publié et ne doit pas en avoir.

Créer des utilisateurs en ligne de commande

L'interface suffit pour gérer les comptes au quotidien, mais la console Symfony de Kimai est précieuse pour automatiser un onboarding ou récupérer un accès. La commande kimai:user:create prend un identifiant, une adresse e-mail et un rôle, puis demande le mot de passe :

docker compose exec kimai /opt/kimai/bin/console kimai:user:create alice [email protected] ROLE_TEAMLEAD

La même console expose kimai:reload pour reconstruire le cache après un changement de configuration, et kimai:update pour appliquer les migrations de base lors d'une installation hors Docker. Tapez bin/console list kimai dans le conteneur pour voir les commandes disponibles sur votre version.

Le modèle de données : clients, projets, activités

Kimai organise le temps sur trois niveaux. Un client porte la devise, le fuseau horaire et les coordonnées de facturation. Un projet appartient à un client et peut avoir des dates de début et de fin, un numéro de commande et un budget. Une activité décrit la nature du travail (développement, réunion, support) ; elle peut être rattachée à un projet ou être globale, donc utilisable partout. Chaque entrée de feuille de temps relie un utilisateur, un projet, une activité, une plage horaire et, si besoin, une description et des étiquettes. Bien concevoir cette hiérarchie au départ évite de longues corrections : un client par entité facturée, un projet par mission ou contrat, des activités globales pour les tâches transverses.

Taux et budgets

  • Taux horaire — définissable sur le client, le projet, l'activité ou l'utilisateur ; le niveau le plus précis s'applique à l'entrée.
  • Taux fixe — un montant forfaitaire par entrée, utile pour une intervention facturée au forfait quelle que soit sa durée.
  • Taux interne — le coût réel d'une heure pour vous, distinct du prix facturé, pour mesurer la rentabilité d'un projet.
  • Budget en temps ou en argent — sur un client, un projet ou une activité, avec un suivi visuel de la consommation.
  • Budget mensuel ou global — un forfait de maintenance mensuel se suit différemment d'un projet au forfait sur toute sa durée.
  • Dépassement — les tableaux de bord signalent la consommation du budget, et un réglage de configuration permet d'autoriser ou de refuser la saisie au-delà.

Rôles, équipes et permissions

Kimai distingue des rôles hiérarchiques, et l'écran Rôles et permissions permet d'ajuster finement ce que chacun voit et modifie. Les équipes complètent ce dispositif : un client, un projet ou une activité réservé à une équipe n'apparaît qu'à ses membres, et le chef d'équipe voit et valide les heures de son équipe sans accéder au reste de l'entreprise. Pour un intervenant externe, créez un compte utilisateur limité à une équipe dédiée.

  • ROLE_USER — saisit et consulte ses propres heures sur les projets qui lui sont accessibles.
  • ROLE_TEAMLEAD — voit et modifie les heures des membres de ses équipes, consulte leurs rapports.
  • ROLE_ADMIN — gère clients, projets, activités, factures et utilisateurs.
  • ROLE_SUPER_ADMIN — accès complet, y compris la configuration système et les permissions.

Facturer à partir des feuilles de temps

Le module de facturation transforme une sélection d'heures en document. Depuis le menu Factures, vous choisissez un client, une période, éventuellement un projet, puis un modèle. Kimai calcule les montants à partir des taux, affiche un aperçu et enregistre la facture avec un statut (en attente, payée, annulée). Les entrées facturées peuvent être marquées comme exportées, ce qui évite de les facturer deux fois et les protège contre une modification ultérieure.

Préparer votre premier modèle de facture

  1. Créer le modèle

    Dans Factures → Modèles, renseignez l'émetteur, l'adresse, les coordonnées bancaires, le délai de paiement et le texte de pied de page.

  2. Choisir le format de rendu

    Sélectionnez un rendu PDF ou HTML pour un document prêt à envoyer, ou un format bureautique si vous retravaillez la facture ailleurs.

  3. Définir la numérotation

    Configurez le format du numéro de facture (préfixe, année, compteur) pour obtenir une séquence continue conforme à vos habitudes comptables.

  4. Paramétrer la taxe

    Indiquez le taux de taxe applicable dans le modèle ; créez un modèle par régime si vous facturez des clients soumis à des taux différents.

TVA et mentions obligatoires

Kimai calcule une taxe à partir du taux saisi dans le modèle, mais il ne connaît pas votre situation fiscale. Les mentions légales, le taux applicable et la conservation des factures dépendent de votre pays et de votre statut : faites valider votre modèle par votre comptable. Si vous tenez une comptabilité complète dans un ERP comme Dolibarr, Kimai peut rester l'outil de saisie du temps et l'export servir de base à la facture finale.

API REST et intégrations

Kimai expose une API REST couvrant clients, projets, activités, feuilles de temps et utilisateurs. Sa documentation interactive est servie par votre propre instance à l'adresse /api/doc, à jour avec la version installée. Pour authentifier un script, créez un jeton d'API depuis votre profil utilisateur, puis passez-le en en-tête :

curl -s -H "Authorization: Bearer VOTRE_JETON" \
  https://kimai.votre-domaine.com/api/timesheets

Un jeton hérite des permissions de son utilisateur : créez un compte de service avec le rôle minimal nécessaire plutôt que d'utiliser le super-administrateur. L'API permet par exemple de démarrer un chronomètre depuis un raccourci, de remonter les heures dans un tableau de bord ou de synchroniser les projets avec votre outil de tickets.

Étendre Kimai avec des plugins

Kimai dispose d'une boutique de plugins sur son site officiel, avec des extensions gratuites et payantes : notes de frais, champs personnalisés, circuits de validation des feuilles de temps, imports depuis d'autres outils. Un plugin est un dossier placé dans var/plugins/. Dans Docker, montez ce dossier sur un volume, sinon il disparaît à la recréation du conteneur — c'est le rôle de kimai_plugins dans le compose ci-dessus. Installation type :

docker compose cp NomDuPluginBundle kimai:/opt/kimai/var/plugins/
docker compose exec kimai /opt/kimai/bin/console kimai:reload --env=prod

Certains plugins ajoutent des tables et fournissent une commande d'installation dédiée ; suivez la fiche du plugin et vérifiez sa compatibilité avec votre version de Kimai avant chaque mise à jour.

Sauvegarde et restauration

L'essentiel tient dans la base MySQL ; les volumes kimai_data et kimai_public complètent la sauvegarde. Un dump logique est plus portable qu'une copie à chaud des fichiers MySQL :

docker compose exec -T db sh -c 'exec mysqldump --single-transaction -u"$MYSQL_USER" -p"$MYSQL_PASSWORD" "$MYSQL_DATABASE"' > kimai-$(date +%F).sql
docker run --rm -v kimai_kimai_data:/data -v "$PWD":/backup alpine tar czf /backup/kimai_data-$(date +%F).tgz -C /data .

Le nom réel du volume est préfixé par le nom du projet Compose : vérifiez-le avec docker volume ls. Pour restaurer, démarrez une pile vide avec le même .env, puis réinjectez le dump :

docker compose exec -T db sh -c 'exec mysql -u"$MYSQL_USER" -p"$MYSQL_PASSWORD" "$MYSQL_DATABASE"' < kimai-AAAA-MM-JJ.sql

Planifiez le dump chaque nuit via cron, copiez-le hors du VPS (Restic, BorgBackup ou stockage objet) et testez une restauration au moins une fois : une sauvegarde jamais restaurée n'est qu'une hypothèse.

Mises à jour sans surprise

  • Sauvegarder d'abord — un dump juste avant la mise à jour permet de revenir en arrière si une migration échoue.
  • Mettre à jour l'image — docker compose pull kimai && docker compose up -d kimai, puis suivez docker compose logs -f kimai. Au démarrage, le conteneur applique les migrations de base automatiquement.
  • Épingler une version — en production, remplacez apache-latest par une étiquette versionnée de l'image pour décider du moment de la montée de version.
  • Lire les notes de version — certaines versions majeures changent des prérequis ou des comportements de plugins.
  • Exporter régulièrement — l'export CSV ou XLSX des feuilles de temps reste une copie lisible, utile pour un audit ou une migration.

Dépannage courant

La plupart des incidents Kimai en Docker se rattachent à quelques causes connues. Commencez toujours par docker compose logs kimai et docker compose ps.

  • « Untrusted Host » ou erreur 400 après l'ajout d'un domaine — le nom d'hôte manque dans TRUSTED_HOSTS. Ajoutez-le puis recréez le conteneur.
  • Erreur 500 et « Permission denied » sur var/ — souvent après une commande console lancée avec un autre utilisateur que celui du serveur web. Rétablissez la propriété avec docker compose exec kimai chown -R www-data:www-data /opt/kimai/var, puis kimai:reload.
  • Changement de configuration sans effet — le cache Symfony sert l'ancienne version : docker compose exec kimai /opt/kimai/bin/console kimai:reload --env=prod.
  • Kimai redémarre en boucle au premier lancement — la base n'est pas prête ou DATABASE_URL est erroné. Vérifiez le healthcheck de db et les identifiants du .env.
  • Liens en http:// derrière le proxy HTTPS — les en-têtes X-Forwarded-Proto ne sont pas transmis ou pas pris en compte ; revoyez la configuration du proxy.
  • Mot de passe oublié sans e-mail configuré — MAILER_URL pointe vers null:// : réinitialisez le mot de passe depuis un compte administrateur ou créez un nouvel administrateur en console.

Kimai face à Toggl Track, Clockify et Harvest

Faites défiler le tableau

CritèreKimai (self-hosted)Toggl TrackClockifyHarvest
LicenceOpen source (MIT)PropriétairePropriétairePropriétaire
HébergementVotre VPSSaaS de l'éditeurSaaS de l'éditeurSaaS de l'éditeur
Emplacement des donnéesVotre base MySQLInfrastructure de l'éditeurInfrastructure de l'éditeurInfrastructure de l'éditeur
Modèle de coûtServeur uniquement, sans frais par utilisateurPalier gratuit limité, puis abonnementPalier gratuit, puis abonnementPalier gratuit limité, puis abonnement
FacturationModule intégré (modèles, numérotation, taxe)Selon l'offre souscriteSelon l'offre souscriteIntégrée au produit
APIREST, jetons, documentation embarquéeRESTRESTREST
PersonnalisationCode source, plugins, configurationParamètres et intégrationsParamètres et intégrationsParamètres et intégrations

Dimensionner le VPS

Kimai est sobre : la charge vient surtout de MySQL et de la génération de rapports sur de longues périodes. Pour un freelance ou une petite équipe, 1 vCPU et 1 à 2 Go de RAM suffisent. Au-delà d'une vingtaine d'utilisateurs actifs, ou si vous produisez régulièrement des rapports annuels et des exports volumineux, prévoyez 2 vCPU et 4 Go, ce qui laisse de la marge au cache InnoDB de MySQL. L'espace disque reste modeste : quelques gigaoctets couvrent des années de feuilles de temps, mais gardez de la place pour les dumps locaux avant leur envoi hors serveur.

Avant d'inviter l'équipe, fixez les règles du jeu dans Paramètres : arrondi des durées, saisie dans le futur autorisée ou non, verrouillage des périodes déjà facturées. Ces choix sont plus simples à poser sur une instance vide que sur des mois d'historique.

Déployez Kimai sur votre VPS en 60 secondes

ServOrbit préconfigure la pile complète (Apache/PHP + MySQL 8) et génère vos identifiants admin — prêt à saisir vos premières heures.

Besoin d'aide ?

Parcourez notre centre d'aide et notre FAQ, ou contactez notre équipe — rappel, WhatsApp ou e-mail. Support en français, anglais et arabe.

Écrire sur WhatsApps'ouvre dans un nouvel onglet