Skip to content
Super 1.7.0 is production-ready — transactional installs with automatic rollback, cron runtime caps (kill_after_secs), and panic-free input handling. See what’s new →

Lifecycle Hooks

Lifecycle hooks run shell commands at fixed points in a single program’s start/stop pipeline. They are configured per program, not globally.

For reacting to system-wide events (crashes, recovery, daemon startup), see System Events — those use a different configuration model (notify.toml with the notify plugin; [[event_hooks]] in OSS).

Hook catalog

HookWhen it runsBlocks start/stop?ExecutionImplemented
pre_startAfter extension before_start, before spawnYes — non-zero exit aborts start; program → FatalAwaited (sync)✅
post_startAfter PID assigned, extension after_start, and process_started eventNoAsync (tokio::spawn)✅
pre_stopAfter user/API stop requested, before SIGTERM / SIGKILLDelays signal until hook returnsAwaited (sync)✅
post_stopAfter process has exitedNoAsync (tokio::spawn)✅

Execution details

  • Commands run via sh -c, so pipes, redirects, and $() work.
  • Empty or whitespace-only commands are skipped.
  • Hook stdout/stderr inherit superd’s logging stream.
  • pre_start failure emits a process_fatal system event with message "Pre-start hook failed".

Configuration

Hooks are stored on each program — in stack files (TOML/JSON), or via the API / CLI / Dashboard. Example: conf/conf.d/my-app.json:

{
  "services": [
    {
      "name": "my-app",
      "command": "./app",
      "hooks": {
        "pre_start": "mkdir -p /tmp/app-data && chmod 700 /tmp/app-data",
        "post_start": "curl -X POST http://consul:8500/register -d '...'",
        "pre_stop": "curl -X POST http://consul:8500/deregister -d '...'",
        "post_stop": "if [ \"$SUPER_EXIT_CODE\" != \"0\" ]; then aws s3 cp logs/app.err s3://archive/; fi"
      }
    }
  ]
}

The same shape works via the API:

{
  "name": "my-app",
  "command": "./app",
  "hooks": {
    "pre_start": "echo checking...",
    "post_start": "echo registered"
  }
}

Where this config lives

SourcePath / APIPersisted to
Stack fileconf/conf.d/* → services[].hookssnapshot.json
Stack applyPUT /api/v1/stack with "hooks": { ... }snapshot.json
CLIsuper add / super update --pre-start "..."snapshot.json
DashboardProgram create/edit formsnapshot.json

Hooks are not defined in super.toml at the global level — super.toml has no program tables at all. Put hooks on each program (stack entry / API / CLI) instead.

Environment variables

Hook scripts receive context via environment variables (in addition to the program’s env / env_file). These are injected by the daemon at run time — distinct from the public environment variables that configure superd/super itself:

Variablepre_startpost_startpre_stoppost_stop
SUPER_ID✅✅✅✅
SUPER_NAME✅✅✅✅
SUPER_HOSTNAME✅✅✅✅
SUPER_GROUP✅ if set✅ if set✅ if set✅ if set
SUPER_PID—✅✅✅
SUPER_EXIT_CODE———✅
SUPER_UPTIME_SECS———✅

The managed child process also receives SUPER_ID, SUPER_NAME, SUPER_HOSTNAME, and optional SUPER_GROUP at spawn time (not the full hook set).

Lifecycle vs system events

Lifecycle hooksSystem events
PurposeSetup/teardown around one program’s start/stopObserve cluster-wide incidents
ConfigPer program hooks (stack JSON / API)Global ([[event_hooks]] in OSS; notify.toml with notify plugin)
Data to scriptEnvironment variablesJSON on stdin (OSS event hooks) or HTTP payload (licensed notify)
Examplesmkdir, Consul register, drain flagSlack alert, archive logs on crash

Related

Was this page helpful? Thanks for your feedback!

Still have questions? Open an issue or browse the source.