Guides

# Connection Guide

Connect your Hermes install, then add a terminal if you need one.

## [Choose your connection](https://cadu.bot/docs/connection#choose)

**Prefer a direct HTTP(S) connection whenever your iPhone can reach the dashboard.** It is the simplest path for the dashboard, chat, and optional terminal features. Use SSH when the dashboard is intentionally private or cannot be reached directly; use Mosh only when you specifically need a resilient terminal session.

Cadu connects to a running Hermes dashboard. You need its address and a dashboard sign-in method. For an SSH connection, you also need an account on the server.

Prefer direct HTTP(S); add SSH or Mosh only when needed
| Connection | What it does | Your choices |
| --- | --- | --- |
| Dashboard and chat | Loads your agents, settings, files, and conversations. Live chat uses a WebSocket connection. | A web address, or HTTP and WebSocket traffic carried through an SSH tunnel. |
| Terminal | Opens a shell in a chat's working folder. | SSH, or Mosh after an initial SSH sign-in. |

Start with **Gateway address** if your iPhone can reach the dashboard over HTTPS, HTTP on a trusted private network, Wi-Fi, or Tailscale. Choose **SSH & Mosh** only when a direct address is unavailable or you deliberately want the dashboard to remain loopback-only behind an SSH tunnel. You can add an SSH or Mosh terminal later while continuing to use a direct web address for normal app communication.

## [Prepare your server](https://cadu.bot/docs/connection#server)

Run these commands on the machine where Hermes is installed. Cadu's SSH connection expects the dashboard to be running already.

### For the preferred direct connection

```
hermes dashboard --host 0.0.0.0 --port 9119 --no-open
```

Use a reachable HTTPS address when possible, or expose the dashboard only to a trusted LAN or VPN. Your phone must be able to reach the server on TCP port 9119, or on the port used by your reverse proxy. A reverse proxy must support WebSocket upgrades for live chat.

### For a private SSH fallback

```
hermes dashboard --host 127.0.0.1 --port 9119 --no-open
```

This listens only on the server itself. Cadu reaches it through SSH. Keep the dashboard process running, and configure dashboard authentication in the next section before connecting.

A non-local bind requires dashboard authentication on current Hermes installations; an interactive launch offers to set it up when no provider is configured.

For access over the public internet, prefer an HTTPS address with a reverse proxy that supports WebSockets. Plain HTTP does not encrypt dashboard credentials or traffic on its own. A Tailscale connection provides its own encrypted network path; keep Tailscale connected on your iPhone. Use SSH when you do not want to expose a directly reachable dashboard address.

If you already have a dashboard running, use its actual host and port instead of starting another copy. Check running dashboard processes with:

```
hermes dashboard --status
```

## [Set a username and password](https://cadu.bot/docs/connection#password)

The **dashboard username and password** belong to Hermes. The **SSH username and password** belong to an operating-system account on your server. Setting one does not create or change the other.

### Interactive setup

When starting a dashboard on a non-local address in an interactive terminal, current Hermes offers authentication setup if no provider is registered. Choose **Username & password**, enter a username, and enter the password twice. Hermes saves a password hash and a session-signing secret. Use those credentials in Cadu's **Sign in to the dashboard → Password** fields.

### Explicit setup, including a private SSH dashboard

For a local-only dashboard, an existing authentication setup, or a service without an interactive prompt, configure the bundled password provider yourself. From your Hermes checkout, using its Python environment, generate a hash with a hidden password prompt:

```
python -c 'import getpass; from plugins.dashboard_auth.basic import hash_password; print(hash_password(getpass.getpass("Dashboard password: ")))'
```

Generate a separate signing secret:

```
python -c 'import secrets; print(secrets.token_urlsafe(32))'
```

In your Hermes configuration, merge these values into the existing `dashboard` section. Replace both placeholders with the generated values and choose your username:

```
dashboard:
  basic_auth:
    username: alex
    password_hash: "PASTE_GENERATED_PASSWORD_HASH"
    secret: "PASTE_GENERATED_SIGNING_SECRET"
```

Keep the signing secret stable so sessions can survive dashboard restarts. Ensure the bundled `basic` authentication plugin is not disabled, then restart the dashboard using your normal process or service manager. In Cadu, enter the original password you typed, not its hash.

For environment-managed deployments, the equivalent settings are `HERMES_DASHBOARD_BASIC_AUTH_USERNAME`, `HERMES_DASHBOARD_BASIC_AUTH_PASSWORD_HASH`, and `HERMES_DASHBOARD_BASIC_AUTH_SECRET`. A configured `HERMES_DASHBOARD_BASIC_AUTH_PASSWORD` takes precedence over a stored hash, so check for an old environment value when changing a password.

To change credentials, update the server's password configuration, restart the dashboard, then update the saved credentials in Cadu under **Settings → Instances**. Editing credentials in Cadu only changes what the app uses to sign in.

## [Connect by web address](https://cadu.bot/docs/connection#web)

1.  On **Add your install**, choose **Gateway address**.
2.  Enter the dashboard's full base address, including its scheme and any port or base path. For example, `https://hermes.example.com`, a private LAN address such as `http://192.168.1.20:9119`, or your Tailscale IP with `http://` and the dashboard port. For Tailscale Serve, use its `https://` address.
3.  Under **Sign in to the dashboard**, select the authentication method your server supports.
4.  Optionally give the install a name, then tap **Connect**. Cadu checks authentication and the live chat connection before completing setup.

Use the dashboard's base address, not a login URL containing a query string, fragment, or embedded username and password. `127.0.0.1` in a direct address points to your iPhone, not your server.

### Password

Enter your Hermes dashboard username and password. **Remember password** controls whether Cadu saves that password for later sign-in. Saved connection credentials use the device's Keychain.

### Browser

Choose **Browser**, tap **Connect**, and sign in on the dashboard's page inside Cadu. Once signed in, tap **Continue**. Cadu imports the dashboard session cookies and verifies the connection. Providers that require a system browser, including Google, do not work in this embedded sign-in flow. Browser sign-in is offered for the web-address method, not the SSH setup method.

### Token

Choose **Token** only if your dashboard is configured to accept a static Hermes session token. Paste that token into **Session token**. It is saved in the Keychain. This is a server-issued connection credential; a model-provider API key will not work, and selecting Token does not enable token authentication on your server.

## [Connect through SSH](https://cadu.bot/docs/connection#ssh)

1.  Start the dashboard on your server and make sure its SSH service is reachable from your iPhone.
2.  Choose **SSH & Mosh**. Enter the **SSH host** as a hostname or IP address without `ssh://`, your server account's **SSH username**, and its **SSH port** (22 by default).
3.  Choose **Password** and enter the server account password, or choose **Private key** and import an OpenSSH Ed25519 or RSA private key. Enter its passphrase if it has one. The server must already allow that account and authentication method.
4.  Set **Dashboard host** to the address reachable from the SSH server, usually `127.0.0.1`. Set **Port** to the dashboard port, usually `9119`. This is separate from SSH port 22.
5.  Leave **Terminal protocol** on **SSH**, or configure Mosh as described below. Under **Sign in to the dashboard**, enter the dashboard password credentials or a supported session token.
6.  Tap **Connect**. On the first connection, compare the displayed SSH fingerprint with the server's fingerprint through a trusted channel, then choose **Trust and connect**.

Cadu opens a local tunnel and carries dashboard requests and live chat through it. The dashboard host is interpreted from the server's side: here, `127.0.0.1` correctly means the SSH server itself. The SSH service must permit TCP forwarding to that host and port.

For an existing install, open its **Connection** settings and choose **Add SSH & Mosh**. In that editor, the target fields are named **Host on SSH Server** and **Dashboard Port**. Adding this tunnel changes how the dashboard is reached. Keep the direct Gateway address as the primary connection whenever it is reachable; use the SSH-backed instance when you need the private fallback.

## [Add a terminal connection](https://cadu.bot/docs/connection#terminal)

You can keep using HTTPS for agents and chat while adding a shell on the same server.

1.  Open **Settings → Instances** and select your saved install.
2.  In the **Terminal** card, choose **Add SSH or Mosh** (or the existing connection).
3.  Enter the SSH host, username, port, and password or private key. Select the terminal protocol, then save the terminal settings and the instance.
4.  Open a chat's **More** menu and choose **Terminal**. The shell opens in that chat's working folder, which must exist and be accessible on the terminal server.

These terminal settings leave your dashboard connection as configured. If the install already uses an SSH tunnel and has no separate terminal configuration, the terminal reuses the tunnel's SSH details. A separately saved terminal connection takes precedence.

## [Configure Mosh](https://cadu.bot/docs/connection#mosh)

Mosh is an optional terminal protocol designed to tolerate network changes and brief interruptions. It starts a session through SSH, then carries the interactive terminal over encrypted UDP. Dashboard requests and chat continue to use your web connection or SSH tunnel.

1.  Install `mosh-server` on the terminal server using that server's package manager. It must be executable by your SSH account.
2.  In the SSH or terminal settings, select **Mosh** under **Terminal protocol**.
3.  Leave **Mosh Server** as `mosh-server` if it is on the remote command search path, or enter its full executable path.
4.  Leave **UDP Port or Range** empty to use the default range, `60000–61000`. To restrict it, enter a single port such as `60000` or a colon-separated range such as `60000:60010`.
5.  Allow the chosen UDP ports through the server firewall and any intervening network or VPN rules. The iPhone must reach them on the SSH server's address. Save and open a terminal to test it.

SSH is still needed to authenticate and start Mosh. Allowing TCP port 22 alone is not enough, and Mosh's UDP traffic does not travel through the dashboard's SSH tunnel. If your network cannot carry UDP to the server, select SSH for the terminal.

## [Connection options](https://cadu.bot/docs/connection#options)

Open **Connection options** during setup, or the saved instance's **Connection** settings.

**Second Address**

Set a fallback address for the same install, for example a LAN address alongside an external hostname. Cadu checks both addresses and prefers the main one when it responds. Direct fallback options are hidden when using an SSH tunnel.

**Trust Self-Signed Certificate**

Allows an HTTPS install whose certificate cannot be verified normally. This disables certificate verification for that install's configured addresses; use it only when you trust the endpoint and network. It does not configure HTTPS on the server.

**Custom Headers**

Add the header names and values required by an authenticating proxy. Cadu includes them in requests to the configured install, including the chat connection. Configure these before connecting if the proxy requires them.

### Reverse proxies and live chat

A working login page is only part of the connection. Your proxy must also pass dashboard API requests, session cookies, and WebSocket upgrades. Password sign-in uses `/auth/password-login`; Cadu checks `/api/auth/me`, obtains a chat ticket from `/api/auth/ws-ticket`, then opens `/api/ws`. Preserve the dashboard's base path if it is hosted under a URL prefix.

## [Troubleshooting](https://cadu.bot/docs/connection#troubleshooting)

Use the failing step to narrow down the problem
| What you see | What to check |
| --- | --- |
| Dashboard discovery failed | Check that the dashboard is running, the URL includes the correct scheme and port, and the phone has a route to it. For a direct connection, try its address in the phone's browser. Keep Tailscale active when using a Tailscale address. |
| Dashboard password sign-in failed | Use the dashboard credentials, not the SSH account. Confirm that the basic password provider is enabled and restart the dashboard after configuration changes. Check environment overrides if a new password does not work. |
| Browser sign-in cannot finish | Finish the dashboard login before tapping Continue. If the provider rejects embedded browsers, use dashboard password authentication or an already-supported static token. |
| WebSocket authorization or chat connection failed | The dashboard may be reachable while the proxy blocks chat. Check the ticket endpoint, session cookies, and WebSocket upgrades for the chat endpoint. |
| SSH connection failed | Check the SSH host, TCP port, server username, password or key passphrase. If SSH succeeds but dashboard discovery fails, check the dashboard target host and port and the server's TCP forwarding permissions. |
| SSH identity changed | Verify the server's current host key before trusting it again. The app rejects a changed key rather than silently accepting a different server. |
| Mosh could not start | Check that mosh-server is installed, its configured path is correct, and the chat's working folder is accessible to your SSH account. |
| Mosh did not answer | Check UDP reachability for the configured range, including firewall and VPN rules. A successful SSH login does not prove UDP is reachable. |
