ExRatatui.SSH.Daemon (ExRatatui v0.7.1)

Copy Markdown View Source

GenServer that owns an OTP :ssh.daemon/2 listening for TUI clients.

This is the transport-level supervisor for ExRatatui.App under transport: :ssh. It starts an :ssh daemon on the requested port, registers the app module as an SSH subsystem + default shell, and tears the daemon down on shutdown. Each connected SSH client gets its own ExRatatui.SSH channel process, which in turn supervises its own internal server running the app — so a single Daemon can serve many concurrent clients without any shared state between them.

Usage

Typically you don't start this directly; use ExRatatui.App routes start_link(transport: :ssh, ...) through here. But for full control you can add it to a supervision tree by hand:

children = [
  {ExRatatui.SSH.Daemon,
   mod: MyApp.TUI,
   port: 2222,
   system_dir: ~c"/etc/ssh",
   user_dir: ~c"/var/ssh/users"}
]

Options

  • :mod (required) — the ExRatatui.App module to serve.
  • :port (default 2222) — TCP port to listen on. 0 picks a random free port — call port/1 on the daemon pid to discover the chosen port.
  • :system_dir — path to the daemon's host key directory, forwarded as-is to :ssh.daemon/2. May be a binary or charlist; binaries are converted automatically.
  • :auto_host_key (default false) — when true, the daemon resolves the OTP application that owns :mod, ensures <priv_dir>/ssh/ exists, and generates a 2048-bit RSA host key there on first boot (ssh_host_rsa_key). Subsequent boots reuse the same key. Set :system_dir explicitly to override the directory; passing both raises. Intended for "drop into a supervision tree and it just works" setups (Phoenix admin TUIs, internal tools); production deployments should keep an explicit :system_dir under their own configuration management.
  • :user_dir — path to client-authentication key material.
  • :authorized_keys — forwarded through to :ssh.daemon/2.
  • :name — process name (default __MODULE__, pass nil to skip).
  • :app_opts — extra opts that will be merged into every client's mount/1 callbacks (e.g. shared PubSub topic names).
  • Any other keyword pair is forwarded verbatim to :ssh.daemon/2, so e.g. :pwdfun, :idle_time, :profile all work unchanged.

Testability

:daemon_starter and :daemon_stopper keyword options let tests substitute fakes for &:ssh.daemon/2 and &:ssh.stop_daemon/1 so the GenServer can be exercised without starting a real SSH listener. The real functions are the defaults; production callers never pass either.

Summary

Functions

Returns a specification to start this module under a supervisor.

Returns the {:ok, daemon_ref} handle of the underlying OTP :ssh daemon, or {:error, :not_started} if it isn't up.

Returns the port the daemon is listening on.

Starts a supervised SSH daemon serving the given ExRatatui.App module. Returns the daemon's process pid on success.

Types

t()

@type t() :: %ExRatatui.SSH.Daemon{
  daemon_ref: term() | nil,
  daemon_stopper: (term() -> :ok),
  mod: module(),
  port: non_neg_integer()
}

Functions

child_spec(init_arg)

Returns a specification to start this module under a supervisor.

See Supervisor.

daemon_ref(server \\ __MODULE__)

@spec daemon_ref(GenServer.server()) :: {:ok, term()} | {:error, :not_started}

Returns the {:ok, daemon_ref} handle of the underlying OTP :ssh daemon, or {:error, :not_started} if it isn't up.

port(server \\ __MODULE__)

@spec port(GenServer.server()) :: non_neg_integer()

Returns the port the daemon is listening on.

start_link(opts)

@spec start_link(keyword()) :: GenServer.on_start()

Starts a supervised SSH daemon serving the given ExRatatui.App module. Returns the daemon's process pid on success.

See the module docs for the full list of accepted options.