# `ExRatatui.SSH.Daemon`
[🔗](https://github.com/mcass19/ex_ratatui/blob/v0.7.1/lib/ex_ratatui/ssh/daemon.ex#L1)

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.

# `t`

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

# `child_spec`

Returns a specification to start this module under a supervisor.

See `Supervisor`.

# `daemon_ref`

```elixir
@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`

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

Returns the port the daemon is listening on.

# `start_link`

```elixir
@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.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
