service

package
v0.11.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 6, 2026 License: MIT Imports: 13 Imported by: 0

Documentation

Overview

Package service installs the `herrscher serve` daemon as a native, boot-started background service on Linux (systemd user unit), macOS (launchd LaunchAgent), and Windows (Task Scheduler onlogon task).

The design separates a pure planner (BuildPlan / BuildUninstall, testable on any OS) from the executor (Install / Uninstall, which writes files and runs the platform commands). Secrets never live in the generated unit: every platform sources an env file (mode 0600) that holds the gateway secrets et al., and the planner only ever creates that file as an empty template — it never overwrites an existing one and never echoes a token.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Build

func Build(ctx context.Context, src, binPath string) error

Build compiles the herrscher binary from src to binPath. `go build -o` writes a new file and renames it into place, so replacing the live binary is safe while the daemon runs (the restart then picks up the new file).

func Install

func Install(ctx context.Context, c Config) error

Install runs the install plan for the current OS: it writes the unit/launcher and secrets template, then enables and starts the service.

func InstalledBinPath

func InstalledBinPath(c Config) (string, bool)

InstalledBinPath returns the binary path baked into the installed service unit's ExecStart, so `service update` rebuilds the binary the service actually runs — not whatever binary happened to invoke the CLI (running it from a build dir would otherwise rebuild that throwaway binary and leave the daemon stale). Returns ("", false) when it can't be determined: unit absent, or an OS whose launcher this doesn't parse (only the linux systemd unit is read).

func Pull

func Pull(ctx context.Context, src string) error

Pull fast-forwards the source checkout. --ff-only fails loudly rather than creating a merge commit when local and remote have diverged.

func Restart

func Restart(ctx context.Context, c Config) error

Restart restarts the service inline (for a separate caller process, e.g. the `herrscher service restart` CLI — never the daemon restarting itself).

func RestartDetached

func RestartDetached(ctx context.Context, c Config) error

RestartDetached restarts the service out-of-band so it survives the caller being killed mid-restart — required when the daemon restarts *itself* (e.g. from /service restart). On Linux the daemon shares the unit's cgroup, which systemd kills on stop, so the restart is scheduled as a transient timer unit (systemd-run) that lives outside that cgroup. launchd/Task Scheduler manage the service from a separate process domain, so a normal restart already survives there.

func Smoke

func Smoke(ctx context.Context, binPath string) error

Smoke runs the freshly built binary with `--help`, which prints usage and exits 0 without touching the network. A non-zero exit means the new binary is broken (won't even parse its CLI), so the caller must not restart into it. The daemon keeps running its old in-memory image; only the on-disk file changed.

func SourceVersion

func SourceVersion(ctx context.Context, src string) string

SourceVersion returns the short commit of the source checkout, or "" if it can't be determined (best-effort, for user-facing messages only).

func Status

func Status(ctx context.Context, c Config) error

Status prints the platform's service status to stdout/stderr.

func Uninstall

func Uninstall(ctx context.Context, c Config) error

Uninstall stops and removes the service for the current OS.

func Update

func Update(ctx context.Context, c Config, src string, pull bool) error

Update pulls (optional), rebuilds, smoke-tests, and restarts the service inline. Used by the `herrscher service update` CLI (a separate process from the daemon).

Types

type Command

type Command struct {
	Argv      []string
	IgnoreErr bool
}

Command is one shell command the plan runs. IgnoreErr commands are best-effort (e.g. unloading a service that isn't loaded yet).

func RestartCommands

func RestartCommands(c Config) ([]Command, error)

RestartCommands returns the platform commands that restart the running service. Some platforms need more than one (stop then start).

func StatusCommand

func StatusCommand(c Config) (Command, error)

StatusCommand returns the command that reports whether the service is active.

type Config

type Config struct {
	GOOS       string   // target OS; "" => runtime.GOOS
	BinPath    string   // absolute path to the herrscher binary
	Home       string   // user home dir
	User       string   // username (for loginctl enable-linger)
	EnvFile    string   // path to the secrets env file (mode 0600)
	HealthAddr string   // --health-addr value; "" omits the flag
	ExtraArgs  []string // extra args appended to `herrscher serve`
	SkipStart  bool     // configure boot-start but don't start now (e.g. token not set yet)

	ConfigPath string // path to the declarative config.json scaffold (template)
	DefaultCmd string // pre-fills the scaffold's "cmd" (from install --cmd)

	// EnvVars are the secret env vars the daemon needs, declared by the compiled-in
	// gateways (from their manifests) plus the core owner id. The planner renders
	// the secrets template and the ready-to-start check from these, so the service
	// package never names a concrete gateway's variables itself. DefaultConfig
	// populates it from the plugin registry.
	EnvVars []EnvVar
}

Config describes the service to install.

func DefaultConfig

func DefaultConfig() (Config, error)

DefaultConfig fills a Config from the current environment (binary path, home, user, default env-file location and health address).

type EnvVar

type EnvVar struct {
	Key      string // env var name (e.g. the gateway's token var)
	Help     string // one-line comment rendered above the line
	Required bool   // the daemon can't start until this is set
}

EnvVar is one secret the daemon reads from its env file, sourced from a gateway manifest's declared config. The planner turns each into a template line; Required ones gate whether install starts the service immediately.

type FileWrite

type FileWrite struct {
	Path     string
	Content  string
	Mode     os.FileMode
	Template bool
}

FileWrite is one file the plan writes. Template files are written only when missing (so an install never clobbers the user's secrets).

type Plan

type Plan struct {
	Files    []FileWrite
	Commands []Command
	Notes    []string // human-facing follow-ups (shown after a successful run)
}

Plan is the full set of side effects for an install or uninstall.

func BuildPlan

func BuildPlan(c Config) (Plan, error)

BuildPlan returns the install plan for c's target OS. Every platform also scaffolds the declarative config.json (template, never clobbered).

func BuildUninstall

func BuildUninstall(c Config) (Plan, error)

BuildUninstall returns the uninstall plan for c's target OS.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL