Please help me debug why this submodule doesn't work

Home.nix

  imports = [
      ./hello2.nix
  ];  

  mystuff.hello2.test1 = {
    enable = true;
  };

  mystuff.hello2.test2 = {
    enable = true;
  };

hello2.nix

{ lib, pkgs, config, ... }:
with lib;                      
let
  cfg = config.mystuff.hello2; #I think this is redundant
in {

  options.mystuff.hello2 = mkOption {
    type = types.attrsOf ( types.submodule(
      {name, ...}:
      {
        enable = mkEnableOption "hello service";

        config = mkIf enable {
          systemd.user.services.name = {
            Install = {
              WantedBy = [ "default.target" ];
            };
            Service = {
              ExecStart = "${pkgs.hello}/bin/hello -g'Hello2, ${escapeShellArg cfg.name}!'";
            };
          };
        };
        
      }
    ));
  };
  
}

This is running using nix / homemanager on a non-nixos OS.

But, no systemd services are created :frowning: I can’t figure out why?

I think you meant to write systemd.user.services.${name}
Also you have to define config at the top-level not inside the submodule, because inside the submodule, config will refer to the top-level of the submodule not your overall config.

2 Likes

I figured it out eventually

git_updater.nix

{ lib, pkgs, config, ... }:
with lib;
let
  cfg = config.services.gitwatcher;
in
{
  options.services.gitwatcher = {

    watchers = mkOption {
      default = { };
      description = ''watches git folders and calls push and pull periodically.'';
      type = with types; attrsOf (submodule ({ config, name, ... }: {
        options = {
          path = mkOption {
            type = types.str;
            description = "the path to watch";
          };
        };
      }
      ));
    };
  };

  config = {
    systemd.user.services = mapAttrs'
      (name: server:
        nameValuePair ("johnhr-git-updater-${name}")
          ({
            Unit.Description = "runs git pull and push on ${server.path}";
            Install.WantedBy = [ "multi-user.target" ];
            Service.ExecStart = toString (
              pkgs.writeShellScript "git_updater"
                ''
                  PATH=$PATH:${lib.makeBinPath [ pkgs.bash pkgs.git pkgs.openssh ]} 
                   ${./git_updater.sh} ${server.path};
                ''
            );
          })
      )
      cfg.watchers;
  };
}

home.nix

  imports = [
    ./git_updater/git_updater.nix
  ];

  services.gitwatcher.watchers = {
    dotfiles.path = "/home/johnhr/repos/dotfiles";
    homelab.path = "/home/johnhr/repos/homelab";
  };

and in case anyone ever needs this:

git_updater.sh

#!/usr/bin/env bash
# set -x #uncomment this to make the shell script print out

git_poll(){
	while true; do
		git -C $1 pull | grep -v "Already up to date."
		git -C $1 push 2>&1 | tr -d '\n' | grep -v "Everything up-to-date"
		sleep 3
	done
}

[[ -z "$1" ]] && { echo "no path was given to watch! exiting..." ; exit 1; } 

git_poll $1