Graceful Shutdown

Ghostunnel supports graceful shutdown: when a shutdown is triggered, it stops accepting new connections and waits for existing connections to drain before exiting. If connections do not drain within the configured timeout, the process force-exits.

Shutdown triggers

There are three ways to initiate a graceful shutdown:

Signals (Unix)

On Unix (Linux, macOS), sending SIGTERM or SIGINT to the Ghostunnel process triggers a graceful shutdown:

# Graceful shutdown via signal
kill -TERM <pid>
kill -INT <pid>    # also sent by Ctrl+C

Note: SIGHUP and SIGUSR1 do not shut down the process. They trigger a reload of certificates and OPA policies instead.

Signals (Windows)

On Windows, only the Interrupt signal (Ctrl+C) triggers shutdown. There are no reload signals on Windows, but --timed-reload can be used to periodically reload certificates and OPA policies on a fixed interval.

HTTP endpoint (/_shutdown)

If --enable-shutdown is set (requires --status), you can trigger a shutdown via HTTP POST:

curl -X POST --cacert test-keys/cacert.pem https://localhost:6060/_shutdown

Any HTTP method other than POST returns 405 Method Not Allowed.

Shutdown sequence

When a shutdown is triggered, the following happens in order:

  1. Status transitions to “stopping”: the /_status endpoint reflects that the process is shutting down.
  2. Status HTTP server begins shutting down: best-effort graceful shutdown of the internal status listener.
  3. Listener closes: Ghostunnel stops accepting new connections.
  4. In-flight connections continue: existing connections are not interrupted. Data continues to flow until both sides close normally.
  5. Force-exit timer starts: a timer begins counting down from the --shutdown-timeout value (default: 5 minutes).
  6. Process exits when either:
    • All in-flight connections have drained (exit code 0), or
    • The shutdown timeout fires (exit code 1).

Flags

FlagDefaultDescription
--shutdown-timeout5mMaximum time to wait for in-flight connections to drain. If connections are still open after this duration, the process force-exits with code 1.
--enable-shutdownfalseEnable the /_shutdown HTTP endpoint on the status port. Requires --status.
--status(none)HOST:PORT (or unix:SOCKET) for the status listener. Required for /_shutdown.

See Command-Line Flags for the full flag reference.

Choosing a shutdown timeout

The default timeout of 5 minutes is deliberately generous. Consider your workload when tuning this value:

  • Short-lived requests (e.g. REST APIs): a lower timeout like 30s or 1m is usually sufficient.
  • Long-lived connections (e.g. streaming, WebSocket-like traffic): you may need to increase the timeout or accept that some connections will be force-closed.
  • Zero-downtime deployments: coordinate the shutdown timeout with your orchestrator’s termination grace period (e.g. Kubernetes terminationGracePeriodSeconds) to avoid the orchestrator killing the process before Ghostunnel’s own timeout fires.

Other flags like --connect-timeout and --conn-max-lifetime also influence connection behavior and may be relevant when tuning shutdown. See Command-Line Flags for the full list.

Integration with systemd

When running as a systemd service with Type=notify-reload, Ghostunnel notifies systemd of its state transitions (ready, reloading, stopping). The graceful shutdown sequence integrates naturally with systemd’s service lifecycle. See Systemd Watchdog for unit file examples and configuration details.