Commit 809f9788 authored by Kira Bruneau's avatar Kira Bruneau Committed by Cabia Rangris
Browse files

nixos/klipper: preserve SAVE_CONFIG for nixos-managed config

Klipper macros that use `SAVE_CONFIG` (eg. bed mesh calibration, PID
tuning, ...) don't currently work with a nixos-managed config.

This can be worked around by using `services.klipper.mutableConfig =
true`, but then you lose out on being able to configure klipper from
NixOS.

This changes the default behaviour so that:

1. The config is stored in `services.klipper.configDir` instead of `/etc`
2. The config is copied instead of symlinked (keeping a timestamped backup of the existing config)
3. The `SAVE_CONFIG` section from the backup is copied over into the new config
4. The backup is deleted if the final config is identical
parent 7093d690
Loading
Loading
Loading
Loading
+34 −23
Original line number Diff line number Diff line
@@ -18,6 +18,13 @@ let
  };
in
{
  imports = [
    (lib.mkRenamedOptionModule
      [ "services" "klipper" "mutableConfigFolder" ]
      [ "services" "klipper" "configDir" ]
    )
  ];

  ##### interface
  options = {
    services.klipper = {
@@ -52,23 +59,22 @@ in
        default = false;
        example = true;
        description = ''
          Whether to copy the config to a mutable directory instead of using the one directly from the nix store.
          This will only copy the config if the file at `services.klipper.mutableConfigPath` doesn't exist.
          Whether to manage the config outside of NixOS.

          It will still be initialized with the defined NixOS config if the file doesn't already exist.
        '';
      };

      mutableConfigFolder = lib.mkOption {
      configDir = lib.mkOption {
        type = lib.types.path;
        default = "/var/lib/klipper";
        description = "Path to mutable Klipper config file.";
        description = "Path to Klipper config file.";
      };

      configFile = lib.mkOption {
        type = lib.types.nullOr lib.types.path;
        default = null;
        description = ''
          Path to default Klipper config.
        '';
        description = "Path to default Klipper config.";
      };

      octoprintIntegration = lib.mkOption {
@@ -162,11 +168,6 @@ in
      }
    ];

    environment.etc = lib.mkIf (!cfg.mutableConfig) {
      "klipper.cfg".source =
        if cfg.settings != null then format.generate "klipper.cfg" cfg.settings else cfg.configFile;
    };

    services.klipper = lib.mkIf cfg.octoprintIntegration {
      user = config.services.octoprint.user;
      group = config.services.octoprint.group;
@@ -178,9 +179,7 @@ in
          "--input-tty=${cfg.inputTTY}"
          + lib.optionalString (cfg.apiSocket != null) " --api-server=${cfg.apiSocket}"
          + lib.optionalString (cfg.logFile != null) " --logfile=${cfg.logFile}";
        printerConfigPath =
          if cfg.mutableConfig then cfg.mutableConfigFolder + "/printer.cfg" else "/etc/klipper.cfg";
        printerConfigFile =
        printerConfig =
          if cfg.settings != null then format.generate "klipper.cfg" cfg.settings else cfg.configFile;
      in
      {
@@ -188,19 +187,31 @@ in
        wantedBy = [ "multi-user.target" ];
        after = [ "network.target" ];
        preStart = ''
          mkdir -p ${cfg.mutableConfigFolder}
          ${lib.optionalString (cfg.mutableConfig) ''
            [ -e ${printerConfigPath} ] || {
              cp ${printerConfigFile} ${printerConfigPath}
              chmod +w ${printerConfigPath}
          mkdir -p ${cfg.configDir}
          pushd ${cfg.configDir}
          if [ -e printer.cfg ]; then
            ${
              if cfg.mutableConfig then
                ":"
              else
                ''
                  # Backup existing config using the same date format klipper uses for SAVE_CONFIG
                  old_config="printer-$(date +"%Y%m%d_%H%M%S").cfg"
                  mv printer.cfg "$old_config"
                  # Preserve SAVE_CONFIG section from the existing config
                  cat ${printerConfig} <(printf "\n") <(sed -n '/#*# <---------------------- SAVE_CONFIG ---------------------->/,$p' "$old_config") > printer.cfg
                  ${pkgs.diffutils}/bin/cmp printer.cfg "$old_config" && rm "$old_config"
                ''
            }
          ''}
          mkdir -p ${cfg.mutableConfigFolder}/gcodes
          else
            cat ${printerConfig} > printer.cfg
          fi
          popd
        '';

        serviceConfig =
          {
            ExecStart = "${cfg.package}/bin/klippy ${klippyArgs} ${printerConfigPath}";
            ExecStart = "${cfg.package}/bin/klippy ${klippyArgs} ${cfg.configDir}/printer.cfg";
            RuntimeDirectory = "klipper";
            StateDirectory = "klipper";
            SupplementaryGroups = [ "dialout" ];