diff --git a/modules/sops/templates/default.nix b/modules/sops/templates/default.nix index 3a53cb8..97952d2 100644 --- a/modules/sops/templates/default.nix +++ b/modules/sops/templates/default.nix @@ -65,6 +65,24 @@ in { File used as the template. When this value is specified, `sops.templates..content` is ignored. ''; }; + restartUnits = lib.mkOption { + type = lib.types.listOf lib.types.str; + default = [ ]; + example = [ "sshd.service" ]; + description = '' + Names of units that should be restarted when the rendered template changes. + This works the same way as . + ''; + }; + reloadUnits = lib.mkOption { + type = lib.types.listOf lib.types.str; + default = [ ]; + example = [ "sshd.service" ]; + description = '' + Names of units that should be reloaded when the rendered template changes. + This works the same way as . + ''; + }; }; })); default = { }; diff --git a/pkgs/sops-install-secrets/main.go b/pkgs/sops-install-secrets/main.go index 42c9d5e..391eb7d 100644 --- a/pkgs/sops-install-secrets/main.go +++ b/pkgs/sops-install-secrets/main.go @@ -51,20 +51,22 @@ type loggingConfig struct { } type template struct { - Name string `json:"name"` - Content string `json:"content"` - Path string `json:"path"` - Mode string `json:"mode"` - Owner *string `json:"owner,omitempty"` - UID int `json:"uid"` - Group *string `json:"group,omitempty"` - GID int `json:"gid"` - File string `json:"file"` - value []byte - mode os.FileMode - content string - owner int - group int + Name string `json:"name"` + Content string `json:"content"` + Path string `json:"path"` + Mode string `json:"mode"` + Owner *string `json:"owner,omitempty"` + UID int `json:"uid"` + Group *string `json:"group,omitempty"` + GID int `json:"gid"` + File string `json:"file"` + RestartUnits []string `json:"restartUnits"` + ReloadUnits []string `json:"reloadUnits"` + value []byte + mode os.FileMode + content string + owner int + group int } type manifest struct { @@ -951,6 +953,8 @@ func handleModifications(isDry bool, logcfg loggingConfig, symlinkPath string, s if err != nil { if os.IsNotExist(err) { // File did not exist before + restart = append(restart, template.RestartUnits...) + reload = append(reload, template.ReloadUnits...) newTemplates[template.Name] = true continue } @@ -964,6 +968,8 @@ func handleModifications(isDry bool, logcfg loggingConfig, symlinkPath string, s } if !bytes.Equal(oldData, newData) { + restart = append(restart, template.RestartUnits...) + reload = append(reload, template.ReloadUnits...) modifiedTemplates[template.Name] = true } } @@ -1156,7 +1162,8 @@ func writeTemplates(targetDir string, templates map[string]*template, keysGID in if !userMode { if err := os.Chown(fp, template.owner, template.group); err != nil { return fmt.Errorf("cannot change owner/group of '%s' to %d/%d: %w", fp, template.owner, template.group, err) - } } + } + } } return nil } diff --git a/pkgs/sops-install-secrets/nixos-test.nix b/pkgs/sops-install-secrets/nixos-test.nix index e36bfe7..765d8be 100644 --- a/pkgs/sops-install-secrets/nixos-test.nix +++ b/pkgs/sops-install-secrets/nixos-test.nix @@ -344,10 +344,14 @@ in { reloadUnits = [ "reload-trigger.service" ]; }; - templates.test_template.content = '' - this is a template with - a secret: ${config.sops.placeholder.test_key} - ''; + templates.test_template = { + content = '' + this is a template with + a secret: ${config.sops.placeholder.test_key} + ''; + restartUnits = [ "restart-unit.service" "reload-unit.service" ]; + reloadUnits = [ "reload-trigger.service" ]; + }; }; system.switch.enable = true; @@ -421,6 +425,22 @@ in { machine.succeed("test -f /restarted") machine.succeed("test -f /reloaded") + # Cleanup the marker files. + machine.succeed("rm /restarted /reloaded") + + # Ensure the template is changed + machine.succeed(": > /run/secrets/rendered/test_template") + + # The template is changed, now something should happen + machine.succeed("/run/current-system/bin/switch-to-configuration test") + + # Ensure something happened + machine.succeed("test -f /restarted") + machine.succeed("test -f /reloaded") + + # Cleanup the marker files. + machine.succeed("rm /restarted /reloaded") + with subtest("change detection"): machine.succeed("rm /run/secrets/test_key") machine.succeed("rm /run/secrets/rendered/test_template")