Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

kimai: init at 2.10.0 #296049

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions nixos/doc/manual/release-notes/rl-2405.section.md
Expand Up @@ -88,6 +88,8 @@ In addition to numerous new and upgraded packages, this release has the followin
Matter Controller Server exposing websocket connections for use with other services, notably Home Assistant.
Available as [services.matter-server](#opt-services.matter-server.enable)

- [Kimai](https://www.kimai.cloud/), Kimai is a web-based multi-user time-tracking application. Works great for everyone: freelancers, companies, organizations - everyone can track their times, generate reports, create invoices and do so much more.

- [Anki Sync Server](https://docs.ankiweb.net/sync-server.html), the official sync server built into recent versions of Anki. Available as [services.anki-sync-server](#opt-services.anki-sync-server.enable).
The pre-existing [services.ankisyncd](#opt-services.ankisyncd.enable) has been marked deprecated and will be dropped after 24.05 due to lack of maintenance of the anki-sync-server softwares.

Expand Down
1 change: 1 addition & 0 deletions nixos/modules/module-list.nix
Expand Up @@ -1322,6 +1322,7 @@
./services/web-apps/kasmweb/default.nix
./services/web-apps/kavita.nix
./services/web-apps/keycloak.nix
./services/web-apps/kimai.nix
./services/web-apps/komga.nix
./services/web-apps/lanraragi.nix
./services/web-apps/lemmy.nix
Expand Down
218 changes: 218 additions & 0 deletions nixos/modules/services/web-apps/kimai.nix
@@ -0,0 +1,218 @@
{ config, pkgs, lib, ... }:

with lib;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
with lib;

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

something wrong with lib?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It makes difficult for anyone to immediately see what's being used from lib.

Instead use something like

let
  inherit (lib) mkOption ...;
in
  ...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


let
userCfg = config.services.kimai;
kimaiDrv = pkgs.kimai.override {
consoleCmd = userCfg.consoleCmd;
databaseUrl = userCfg.databaseUrl;
mailerFrom = userCfg.mailerFrom;
mailerUrl = userCfg.mailerUrl;
appSecret = userCfg.appSecret;
corsAllowOrigin = userCfg.corsAllowOrigin;
};
kimaiName = "kimai";
kimaiDataDir = "${kimaiDrv}/public";
in
{
options.services.kimai = {
enable = mkEnableOption (lib.mdDoc "Kimai web client");
consoleCmd = mkOption {
type = types.str;
default = "kimai-console";
description = lib.mdDoc ''
The name of the binary for Kimai. This would be the binary that can be called
for the Kimai commands, usually shown as `/bin/console` in the docs, but renamed in
this package to `kimai-console` for clarity.

- https://www.kimai.org/documentation/commands.html

This value becomes the name of the file, so don't use an invalid file name.
'';
};
enableDatabase = mkOption {
type = types.bool;
default = true;
description = lib.mdDoc ''
Whether to configure mysql database for you, or not.
If you disabled this option then you will need to adjust the `databaseUrl` option
to fit your needs.
'';
};
mysqlPackage = mkPackageOptionMD pkgs "mysql80" {
extraDescription = lib.mdDoc ''
Mysql package to use.
Note: changing this may require changing the `databaseUrl` option too.
'';
};
Comment on lines +45 to +48
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Mysql package to use.
Note: changing this may require changing the `databaseUrl` option too.
'';
};
Mysql package to use.
Note: changing this may require changing the `databaseUrl` option, too.
'';
};

databaseUrl = mkOption {
type = types.str;
default = "mysql://kimai:@127.0.0.1:3306/kimai_db?charset=utf8mb4&serverVersion=8.0.34";
description = lib.mdDoc ''
The DATABASE_URL env var from KIMAI:
https://github.com/kimai/kimai/blob/main/.env.dist#L22C1-L22C13
'';
};
mailerFrom = mkOption {
type = types.str;
default = "kimai@example.com";
description = lib.mdDoc ''
The MAILER_FROM env var from KIMAI:
https://github.com/kimai/kimai/blob/main/.env.dist#L28
'';
};
mailerUrl = mkOption {
type = types.str;
default = "null://null";
description = lib.mdDoc ''
The MAILER_URL env var from KIMAI:
https://github.com/kimai/kimai/blob/main/.env.dist#L30
'';
};
appSecret = mkOption {
type = types.str;
default = "change_this_to_something_unique";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be read from a file to be secure

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@SuperSandro2000
Is it considered safer to ask for a file path instead of a string? Because I have not seen that in a lot of other packages.

description = lib.mdDoc ''
The APP_SECRET env var from KIMAI:
https://github.com/kimai/kimai/blob/main/.env.dist#L38
'';
};
corsAllowOrigin = mkOption {
type = types.str;
default = "^https?://localhost(:[0-9]+)?$";
description = lib.mdDoc ''
The CORS_ALLOW_ORIGIN env var from KIMAI:
https://github.com/kimai/kimai/blob/main/.env.dist#L47

Unlikely, that you need to change this one
'';
};
nginxProxy = {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use the nginx vhost suboptions or omit this

enable = mkEnableOption (lib.mdDoc "VirtualHost for Kimai");
vHost = mkOption {
type = types.str;
description = lib.mdDoc ''
The virtual host to be used with kimai.
This correspondes to the value in services.nginx.virtualHosts.<vHost>
Example: "kimai.domain.tld"
'';
};
useACMEHost = mkOption {
type = types.str;
description = lib.mdDoc ''
The ACME host to use for the nginx virtualHost, for example if you have
the following in your configuration:
```
security.acme.certs.<domain-with-cert> = {
group = "nginx";
extraDomainNames = [ kimaiSubdomain.domain.tld ]
};
```
then you would use `<domain-with-cert>` here as the value.
Make sure to set the `onlySSL` option too.
'';
};
onlySSL = mkOption {
type = types.bool;
description = lib.mdDoc ''
`onlySSL` option for nginx virtualHosts.
Make sure to set the `useACMEHost` option.
'';
};
};
};

config = mkIf userCfg.enable {
users.users.${kimaiName} = {
description = "The Kimai service user";
isSystemUser = true;
group = kimaiName;
};
users.groups.${kimaiName} = {};
Comment on lines +127 to +132
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

User and group should only be created if it is the default user and group.


services.nginx = mkIf userCfg.nginxProxy.enable {
enable = true;
recommendedProxySettings = true;
recommendedTlsSettings = true;
virtualHosts = {
${userCfg.nginxProxy.vHost} = {
onlySSL = userCfg.nginxProxy.onlySSL;
useACMEHost = userCfg.nginxProxy.useACMEHost;
root = "${kimaiDataDir}";
extraConfig = "index index.php;";
locations."~ /\.ht" = {
extraConfig = ''
deny all;
'';
};
locations."/" = {
tryFiles = "$uri /index.php$is_args$args";
};
locations."~ ^/index\.php(/|$)" = {
extraConfig = ''
fastcgi_pass unix:${config.services.phpfpm.pools.${kimaiName}.socket};
fastcgi_split_path_info ^(.+\.php)(/.+)$;
include ${pkgs.nginx}/conf/fastcgi.conf;
'';
};
};
};
};

# this is the service that runs our kimai server
services.phpfpm.pools.${kimaiName} = {
user = kimaiName;
group = kimaiName;
settings = {
"listen.owner" = mkIf userCfg.nginxProxy.enable config.services.nginx.user;
"pm" = "dynamic";
"pm.max_children" = 32;
"pm.max_requests" = 500;
"pm.start_servers" = 2;
"pm.min_spare_servers" = 2;
"pm.max_spare_servers" = 5;
"php_admin_value[error_log]" = "stderr";
"php_admin_flag[log_errors]" = true;
"catch_workers_output" = true;
};
phpEnv."PATH" = lib.makeBinPath [ pkgs.php ];
};

services.mysql = mkIf userCfg.enableDatabase {
enable = true;
package = userCfg.mysqlPackage;
ensureUsers = [
{
name = kimaiName;
ensurePermissions = {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't eval anymore.

"kimai_db.*" = "ALL PRIVILEGES";
};
}
];
ensureDatabases = [ "kimai_db" ];
# Requires changing the auth for the kimai to work properly,
# because kimai does not use socket_auth,
# which mysql package uses for new users.
initialScript = builtins.toFile "mysql_initial.sql" "alter user kimai@localhost identified with mysql_native_password by ''";
};

systemd.services.phpfpm-kimai = {
restartTriggers = [ kimaiDrv ];
# these preStart scripts run as root
preStart = ''
mkdir -p /var/lib/kimai/var/log
mkdir -p /var/lib/kimai/var/cache
mkdir -p /var/lib/kimai/var/data
mkdir -p /var/lib/kimai/var/plugins
Comment on lines +204 to +207
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These paths should be configurable so people can host multiple instances of it or use non-standard locations.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

More importantly they should be using tmpfiles.d

# `cache:clear` is necessary to clear previous references to store derivation.
# `cache:clear` must run before the chown, otherwise
# the cache is created only for root user inside /var/lib/kimai/var/cache
${kimaiDrv}/bin/${userCfg.consoleCmd} cache:clear
chown -R kimai:kimai /var/lib/kimai
'';
};

environment.systemPackages = [ kimaiDrv ];
};
}
12 changes: 12 additions & 0 deletions pkgs/by-name/ki/kimai/composer2nix/README.md
@@ -0,0 +1,12 @@
These files were created with `composer2nix` by using the `composer.json` from the kimai repo.

After creating the files with `composer2nix`:
- The `composerEnv.buildPackage` in `php-packages.nix` is to be adjusted and the repo files can be removed. The `src` needs be replaced with `fetchFromGitHub`, and the `meta` attributes adjusted.
- The `default.nix` should stay mostly the same, although `composer2nix` will generate its own default file.

- composer2nix:
- https://github.com/svanderburg/composer2nix
- kimai:
- https://github.com/kimai/kimai/tree/main

Additionally the `filterSrc` in `composer-env.nix` needs to be removed to satisfy ofBorg CI.