diff --git a/nixos/doc/manual/release-notes/rl-2505.section.md b/nixos/doc/manual/release-notes/rl-2505.section.md
index a82932ce66262d..6f1ec85a83b370 100644
--- a/nixos/doc/manual/release-notes/rl-2505.section.md
+++ b/nixos/doc/manual/release-notes/rl-2505.section.md
@@ -16,6 +16,8 @@
- [Omnom](https://github.com/asciimoo/omnom), a webpage bookmarking and snapshotting service. Available as [services.omnom](options.html#opt-services.omnom.enable).
+- [Traccar](https://www.traccar.org/), a modern GPS Tracking Platform. Available as [services.traccar](#opt-services.traccar.enable).
+
- [Amazon CloudWatch Agent](https://github.com/aws/amazon-cloudwatch-agent), the official telemetry collector for AWS CloudWatch and AWS X-Ray. Available as [services.amazon-cloudwatch-agent](#opt-services.amazon-cloudwatch-agent.enable).
- [agorakit](https://github.com/agorakit/agorakit), an organization tool for citizens' collectives. Available with [services.agorakit](#opt-services.agorakit.enable).
diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix
index 3b31c12df77aaf..eaff9dc318dfa8 100644
--- a/nixos/modules/module-list.nix
+++ b/nixos/modules/module-list.nix
@@ -947,6 +947,7 @@
./services/monitoring/telegraf.nix
./services/monitoring/thanos.nix
./services/monitoring/todesk.nix
+ ./services/monitoring/traccar.nix
./services/monitoring/tremor-rs.nix
./services/monitoring/tuptime.nix
./services/monitoring/unpoller.nix
diff --git a/nixos/modules/services/monitoring/traccar.nix b/nixos/modules/services/monitoring/traccar.nix
new file mode 100644
index 00000000000000..8aec927e6c9fbb
--- /dev/null
+++ b/nixos/modules/services/monitoring/traccar.nix
@@ -0,0 +1,125 @@
+{
+ config,
+ lib,
+ pkgs,
+ ...
+}:
+let
+ cfg = config.services.traccar;
+ stateDirectory = "/var/lib/traccar";
+ configFilePath = "${stateDirectory}/config.xml";
+ expandCamelCase = lib.replaceStrings lib.upperChars (map (s: ".${s}") lib.lowerChars);
+ mkConfigEntry = key: value: "${value}";
+ mkConfig =
+ configurationOptions:
+ pkgs.writeText "traccar.xml" ''
+
+
+
+ ${builtins.concatStringsSep "\n" (lib.mapAttrsToList mkConfigEntry configurationOptions)}
+
+ '';
+
+ defaultConfig = {
+ databaseDriver = "org.h2.Driver";
+ databasePassword = "";
+ databaseUrl = "jdbc:h2:${stateDirectory}/traccar";
+ databaseUser = "sa";
+ loggerConsole = "true";
+ mediaPath = "${stateDirectory}/media";
+ templatesRoot = "${stateDirectory}/templates";
+ };
+in
+{
+ options.services.traccar = {
+ enable = lib.mkEnableOption "Traccar, an open source GPS tracking system";
+ settings = lib.mkOption {
+ apply = lib.recursiveUpdate defaultConfig;
+ default = defaultConfig;
+ description = ''
+ {file}`config.xml` configuration as a Nix attribute set.
+ Attribute names are translated from camelCase to dot-separated strings. For instance:
+ {option}`mailSmtpPort = "25"`
+ would result in the following configuration property:
+ `25`
+ Configuration options should match those described in
+ [Traccar - Configuration File](https://www.traccar.org/configuration-file/).
+ Secret tokens should be specified using {option}`environmentFile`
+ instead of this world-readable attribute set.
+ '';
+ };
+ environmentFile = lib.mkOption {
+ type = lib.types.nullOr lib.types.path;
+ default = null;
+ description = ''
+ File containing environment variables to substitute in the configuration before starting Traccar.
+
+ Can be used for storing the secrets without making them available in the world-readable Nix store.
+
+ For example, you can set {option}`services.traccar.settings.databasePassword = "$TRACCAR_DB_PASSWORD"`
+ and then specify `TRACCAR_DB_PASSWORD=""` in the environment file.
+ This value will get substituted in the configuration file.
+ '';
+ };
+ };
+
+ config =
+ let
+ configuration = mkConfig cfg.settings;
+ in
+ lib.mkIf cfg.enable {
+ systemd.services.traccar = {
+ enable = true;
+ description = "Traccar";
+
+ after = [ "network-online.target" ];
+ wantedBy = [ "multi-user.target" ];
+ wants = [ "network-online.target" ];
+
+ preStart = ''
+ # Copy new templates into our state directory.
+ cp -a --update=none ${pkgs.traccar}/templates ${stateDirectory}
+ test -f '${configFilePath}' && rm -f '${configFilePath}'
+
+ # Substitute the configFile from Envvars read from EnvironmentFile
+ old_umask=$(umask)
+ umask 0177
+ ${lib.getExe pkgs.envsubst}/bin/envsubst \
+ -i ${configuration} \
+ -o ${configFilePath}
+ umask $old_umask
+ '';
+
+ serviceConfig = {
+ DynamicUser = true;
+ EnvironmentFile = cfg.environmentFile;
+ ExecStart = "${lib.getExe pkgs.traccar} ${configFilePath}";
+ LockPersonality = true;
+ NoNewPrivileges = true;
+ PrivateDevices = true;
+ PrivateTmp = true;
+ PrivateUsers = true;
+ ProtectClock = true;
+ ProtectControlGroups = true;
+ ProtectHome = true;
+ ProtectHostname = true;
+ ProtectKernelLogs = true;
+ ProtectKernelModules = true;
+ ProtectKernelTunables = true;
+ ProtectSystem = "strict";
+ Restart = "on-failure";
+ RestartSec = 10;
+ RestrictRealtime = true;
+ RestrictSUIDSGID = true;
+ StateDirectory = "traccar";
+ SuccessExitStatus = 143;
+ Type = "simple";
+ # Set the working directory to traccar's package.
+ # Traccar only searches for the DB migrations relative to it's WorkingDirectory and nothing worked to
+ # work around this. To avoid copying the migrations over to the state directory, we use the package as
+ # WorkingDirectory.
+ WorkingDirectory = "${pkgs.traccar}";
+ };
+ };
+ };
+}
diff --git a/pkgs/by-name/tr/traccar/package.nix b/pkgs/by-name/tr/traccar/package.nix
new file mode 100644
index 00000000000000..590f65fddadc24
--- /dev/null
+++ b/pkgs/by-name/tr/traccar/package.nix
@@ -0,0 +1,43 @@
+{
+ fetchzip,
+ lib,
+ pkgs,
+ stdenvNoCC,
+}:
+stdenvNoCC.mkDerivation rec {
+ pname = "traccar";
+ version = "6.5";
+ nativeBuildInputs = [ pkgs.makeWrapper ];
+
+ src = fetchzip {
+ stripRoot = false;
+ url = "https://github.com/traccar/traccar/releases/download/v${version}/traccar-other-${version}.zip";
+ hash = "sha256-XCG3G24oe/qR6LiMJASb9STOnyTCtw+2HigaPawcQvU=";
+ };
+
+ installPhase = ''
+ runHook preInstall
+
+ for dir in lib schema templates web ; do
+ mkdir -p $out/$dir
+ cp -a $dir $out
+ done
+
+ mkdir -p $out/share/traccar
+ install -Dm644 tracker-server.jar $out
+
+ makeWrapper ${pkgs.openjdk}/bin/java $out/bin/traccar \
+ --add-flags "-jar $out/tracker-server.jar"
+
+ runHook postInstall
+ '';
+
+ meta = with lib; {
+ description = "Open source GPS tracking system";
+ homepage = "https://www.traccar.org/";
+ sourceProvenance = with sourceTypes; [ binaryBytecode ];
+ license = licenses.asl20;
+ mainProgram = "traccar";
+ maintainers = with maintainers; [ frederictobiasc ];
+ };
+}