Deployment guide

Kimai

Overview

Kimai is a popular open source, self-hosted time-tracking application for teams and freelancers. From an ordinary browser you record working hours against customers, projects and activities. You then turn those timesheets into invoices and exportable reports, control access with roles and teams, and keep every record private on infrastructure you control.

This SecureAnyCloud image serves Kimai 2.60.0, a Symfony application, behind nginx with PHP 8.3 FPM and OPcache on a hardened Ubuntu 24.04 LTS base, patched at build time. Kimai stores its data in a local MariaDB database, which Kimai recommends for production. The schema is migrated in the image, so the application is ready the moment the VM boots.

What you get:

  • Kimai 2.60.0 served by nginx through the PHP 8.3 front controller, managed by systemd
  • The Kimai web interface on :80 with a super administrator account required to sign in
  • A per-VM application secret, database password and administrator password, generated on first boot and recorded in a root-only file. No shared or default login ships in the image
  • A local MariaDB database, the datastore Kimai recommends for production
  • Two dedicated Azure data disks: the MariaDB data directory at /var/lib/mysql and the Kimai application tree at /opt/kimai, each independently resizable
  • nginx.service, php8.3-fpm.service and mariadb.service as enabled systemd units
  • 24/7 SecureAnyCloud support

Prerequisites

You need an active Azure subscription, an SSH key pair, and a VNet plus subnet in the target region.

Standard_B2s (2 vCPU / 4 GiB RAM) is a sensible starting size. Size up for larger teams and heavier concurrent use.

Configure the network security group (NSG) to allow inbound 22/tcp from your management network and 80/tcp for the web interface. Also allow 443/tcp if you terminate TLS on the VM. Kimai serves plain HTTP on port 80, so for production, terminate TLS in front of it with your own domain.

Step 1 - Deploy from the Azure Marketplace

Sign in to the Azure Portal, choose Create a resource, search the Marketplace for Kimai by SecureAnyCloud, and select Create.

On the Basics tab, pick your subscription, resource group, region and size. Under Administrator account, choose SSH public key and paste your key. Under Inbound port rules, allow SSH (22) and HTTP (80).

Review the two dedicated data disks on the Disks tab, then select Review + create and Create.

Step 2 - Deploy from the Azure CLI

# Accept the Marketplace terms once per subscription (required before the first CLI deploy)
az vm image terms accept --urn sac1647283583153:kimai-ubuntu-24-04:default:latest
az vm create \
  --resource-group <your-rg> \
  --name kimai \
  --image sac1647283583153:kimai-ubuntu-24-04:default:latest \
  --size Standard_B2s \
  --admin-username azureuser \
  --generate-ssh-keys \
  --public-ip-sku Standard

Open port 80 for the web interface:

az vm open-port --resource-group <your-rg> --name kimai --port 80

Step 3 - Confirm the services are running

SSH in as azureuser and confirm that nginx, PHP-FPM and MariaDB are active. nginx serves Kimai on port 80.

systemctl is-active nginx php8.3-fpm mariadb
ss -tlnp | grep ':80 ' | sed 's/ */ /g'

Step 4 - Retrieve the per-VM administrator password

Every VM generates its own administrator password on first boot and writes it, along with the login user and URL, to a root-only credentials file. Read it with sudo:

sudo cat /root/kimai-credentials.txt

Sign in to Kimai with username admin and the kimai.admin.pass value from this file.

To prove the login works from the command line, establish an authenticated session with those credentials. A successful login reaches the dashboard, which no longer contains the sign-in form. A wrong password is bounced back to the sign-in form:

U=$(sudo grep '^kimai.admin.user=' /root/kimai-credentials.txt | cut -d= -f2-);
P=$(sudo grep '^kimai.admin.pass=' /root/kimai-credentials.txt | cut -d= -f2-);
CJ=$(mktemp);
LF=$(curl -s -c "$CJ" http://127.0.0.1/en/login);
T=$(printf '%s' "$LF" | grep -m1 -oE 'name="_csrf_token"[^>]*value="[^"]+"' | sed -E 's/.*value="([^"]+)".*/\1/'); curl -s -b "$CJ" -c "$CJ" -o /dev/null -L --data-urlencode "_csrf_token=$T" --data-urlencode "_username=$U" --data-urlencode "_password=$P" http://127.0.0.1/en/login_check;
BODY=$(curl -s -b "$CJ" -L http://127.0.0.1/); rm -f "$CJ"; case "$BODY" in *_password*) echo "login FAILED";; *) echo "login OK";; esac

Step 5 - Sign in to Kimai

Browse to http://<vm-public-ip>/. Kimai opens on its sign-in screen. Enter username admin and the password from Step 4, then select Login.

Step 6 - The dashboard

After you sign in, you reach the Kimai dashboard. It summarises your recorded working time, your most recent timesheets and your active work. The large start button at the top punches you in against the selected project and activity, so you can begin tracking time straight away.

Step 7 - Record timesheets, customers, projects and activities

Kimai organises time into a customer, project and activity hierarchy. Before you record billable time, create a customer, add a project under that customer, and add one or more activities to the project. From the left-hand menu you can:

  • Open Timesheet to start and stop time records, edit durations, and review the time you have logged.
  • Open Customers to manage the clients you bill, including their address, currency and budget.
  • Open Projects to manage the projects under each customer, with their own budgets, dates and teams.
  • Open Activities to manage the kinds of work you record time against, either globally or per project.
  • Open Invoices to turn recorded time into invoices, and Export to produce CSV, Excel and PDF reports.

To change the administrator password, select your user avatar at the top right of any page, choose Profile, open the Password tab, and set a new password.

Step 8 - Manage users, roles and teams

Kimai supports multiple users with role-based access control. As a super administrator, you can invite colleagues and control what they can see and do.

Open Users under the administration area to create accounts and assign roles (user, teamlead, administrator, super administrator). Open Teams to group users and grant a team access to specific customers, projects and activities, so each person only sees the work that concerns them.

You can also create users from the command line on the VM. The console command prompts interactively for a password, so run it directly in your own terminal:

sudo -u www-data php /opt/kimai/bin/console kimai:user:create alice alice@example.com ROLE_ADMIN

Step 9 - Verify the stack

Confirm the Kimai version, that the services are enabled, and that the web interface answers on port 80:

sudo -u www-data php /opt/kimai/bin/console kimai:version
systemctl is-enabled nginx php8.3-fpm mariadb
curl -s -o /dev/null -w 'Kimai login HTTP %{http_code}\n' http://127.0.0.1/en/login

Step 10 - Where your data lives

The MariaDB data directory and the Kimai application tree each live on their own dedicated Azure data disk, separate from the OS disk. The database is at /var/lib/mysql. The code, .env configuration and var/ runtime data are at /opt/kimai. Both disks are captured into the image and re-provisioned on every VM, and you can resize either tier independently. Confirm the mounts and filesystems:

df -h /var/lib/mysql /opt/kimai | tail -2
for m in /var/lib/mysql /opt/kimai; do findmnt -no SOURCE,TARGET,FSTYPE "$m"; done

Step 11 - Enable HTTPS with Let's Encrypt

The image serves Kimai over HTTP on port 80 so it works immediately behind the VM's public address. For production, put it behind HTTPS. Point a DNS name at the VM and open 443/tcp in the NSG. Then install Certbot and request a certificate, replacing your-domain.example.com with the DNS name that resolves to the VM:

sudo apt-get update
sudo apt-get install -y certbot python3-certbot-nginx
sudo certbot --nginx -d your-domain.example.com

Certbot obtains a certificate, updates the nginx configuration to serve Kimai over HTTPS, and sets up automatic renewal.

Step 12 - Back up and maintain your VM

All of Kimai's data is in the MariaDB database on the /var/lib/mysql disk and the application tree on the /opt/kimai disk. To back up your time-tracking data, snapshot the two Azure data disks from the portal or the CLI, or take a logical database dump:

sudo mariadb-dump kimai > /tmp/kimai-backup.sql

Apply operating system security updates regularly. The image is patched at build time and ships with unattended security upgrades enabled. Because the data lives on its own disks, you can resize either tier independently if your time-tracking store grows.

Security notes

  • Encrypt web traffic. Kimai serves plain HTTP on port 80. For production, put it behind your own TLS-terminating reverse proxy or an Azure Application Gateway with a certificate for your domain, and restrict port 80 in the NSG to trusted networks.
  • Protect the administrator password. The per-VM administrator password lives in /root/kimai-credentials.txt, readable only by root. The application secret and database password are rotated on first boot too, so no shared or default credential ships in the image. Sign in and change the administrator password from the profile menu, and keep a copy somewhere safe.
  • Use API tokens and single sign-on. Kimai exposes a full REST API and supports LDAP and SAML single sign-on. Create scoped API tokens or wire up your identity provider for integrations rather than sharing your login.
  • Keep the VM patched. The image is patched at build time and ships with unattended security upgrades enabled.

Architecture summary

  • Application: Kimai 2.60.0 (Symfony)
  • Web server: nginx serving the public/ document root on port 80
  • Runtime: PHP 8.3 FPM with OPcache
  • Database: MariaDB, data directory on a dedicated data disk at /var/lib/mysql
  • Application disk: dedicated data disk mounted at /opt/kimai (code, .env, var/)
  • Credentials: generated on first boot, written to /root/kimai-credentials.txt (mode 0600)
  • First user: the administrator is a super administrator of the installation

Support

SecureAnyCloud images come with 24/7 support. For questions about this Kimai image or help with your deployment, contact us through the SecureAnyCloud website.

All product and company names are trademarks or registered trademarks of their respective holders. Use of them does not imply any affiliation with or endorsement by them.

Deploy on Azure

Launch Kimai on Ubuntu 24.04 LTS on Azure with 24/7 support from SecureAnyCloud.

View this image

Need Help?

Our support team is available 24/7.

sales@secureanycloud.com

Deploy on Azure