# Trusted SSH host keys ## v1.7.8 — web enrollment and migration Administrators can open a server page and use **SSH host key → Inspect SSH key**, including when statistics/protocol loading fails. Unknown and changed keys have distinct warnings; the server list no longer equates TCP reachability with trusted SSH. Inspection performs SSH key exchange only: no username, password, private key or agent authentication is sent. Server-list refreshes check TCP reachability and local pin presence only, not live SSH identity (`ssh_verified: false`); use **Inspect SSH key** to check the current fingerprint. Refreshing a list never starts an extra SSH key exchange. Inspection uses the same pinned-algorithm preference as Paramiko SSHClient, so an existing RSA pin is not falsely reported changed merely because the server also offers Ed25519 or ECDSA. Compare the displayed algorithm and SHA256 fingerprint with an independent VPS console (use the matching `/etc/ssh/ssh_host_*_key.pub`, not necessarily Ed25519). For replacement, investigate why the old fingerprint changed. Tick the explicit verification checkbox, then **Trust key and retry**. The page reloads and retries normal operations with a fresh connection and reset cooldown. No VPN clients, VPN keys or configurations are changed. Confirmation is signed, expires after five minutes, binds the server UID, host, port and exact candidate key, and re-probes before saving. Restarting the panel invalidates outstanding confirmations. A changed candidate or endpoint requires a fresh inspection. Only admins (not support users) may use these POST endpoints; session/Bearer access controls and same-origin browser checks apply. Confirmations also bind the previous trust entries: a concurrent administrator change requires re-inspection rather than silently overwriting that decision. Endpoint edits are serialized with confirmation in the panel process. Modern browsers' same-origin Fetch Metadata permits TLS-terminating reverse proxies; older browsers require the proxy to preserve the external request origin. The default file is `ssh_known_hosts` beside the resolved `DATA_FILE`: beside `app.py` for source installs, beside the executable for frozen installs, and `/app/data/ssh_known_hosts` for the supplied Docker Compose deployment. Override with `SSH_KNOWN_HOSTS_FILE`. A missing file can be created by enrollment; its parent must be writable. Read-only mounts/files produce an explicit error; make the persistent trust location writable if web enrollment is desired. Updates are serialized within the panel process and use atomic file replacement. Other endpoints (including aliases on shared lines) are preserved; hashed entries and nonstandard ports are supported. Conflicting system `~/.ssh/known_hosts` entries are never silently overridden: correct them independently as the panel OS user, then inspect again. Run one panel writer per trust file; external editors or multiple processes are not coordinated by the in-process lock. Existing manually enrolled entries keep working. The manual procedure below is still supported for read-only/operator-managed trust. `RejectPolicy` remains in force; there is no automatic trust-on-first-use fallback. SSH connections reject unknown or changed host keys before password/public-key authentication. There is no automatic first-use enrollment. Existing SSH user keys and passwords are still supported; server host trust is a separate check. **Upgrade prerequisite:** enroll every managed SSH endpoint manually before upgrade or use the administrator recovery controls after upgrade. Until enrollment, operations fail closed. Do not restore `AutoAddPolicy` as a workaround. Paramiko loads the panel process user's `~/.ssh/known_hosts` and a persistent panel trust file, defaulting to `ssh_known_hosts` beside `DATA_FILE` (normally `/app/data/ssh_known_hosts` in Docker). Set `SSH_KNOWN_HOSTS_FILE` to use another file. An explicitly configured missing, unreadable or malformed file is an error. Bind-mount an operator-managed file read-only, or place it in the existing persistent data volume; do not rely on an ephemeral container layer. Restrict write access to trusted operators and ensure the panel user can read it. ## Initial enrollment 1. Obtain the endpoint's public host key and SHA256 fingerprint using an independent trusted channel, such as the VPS provider console or an existing independently verified administrative SSH session. On the endpoint: ```sh ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub -E sha256 cat /etc/ssh/ssh_host_ed25519_key.pub ``` These are **public host keys**, never client private keys. 2. Confirm the fingerprint independently. `ssh-keyscan` can collect a candidate but cannot authenticate it: never pipe its output directly into trusted known_hosts without comparing fingerprints through the independent channel. 3. Add an OpenSSH known_hosts line to a private candidate trust file: ```text node.example.test ssh-ed25519 [node.example.test]:2222 ssh-ed25519 ``` Use the exact configured SSH hostname/IP and port. A non-default port requires `[host]:port`. Enroll all aliases actually used by the panel. Hostnames do not replace fingerprint verification; DNS changes cannot enroll another key. 4. Validate with `ssh-keygen -lf -E sha256`, preserve a backup, and install the verified file atomically with restricted permissions. Mount or configure it for the panel, then test a read-only SSH operation. ## Controlled rotation and failures A changed key is rejected; do not approve it based on the error message alone. Verify the new fingerprint independently, schedule rotation, back up the trust file, replace the relevant verified entry atomically, and reconnect/restart the panel during the agreed window. Existing pooled SSH transports keep the host identity verified at their original handshake until disconnected; changing the file does not revoke an already-open transport. Paramiko reloads trust on each new handshake. Remove stale entries from both system and panel trust stores; system entries can take precedence over the panel file. If verification fails or the endpoint is unavailable, the operation fails and the normal connection backoff applies. No trust file is rewritten by the panel. Restore only a previously verified backup when rolling back trust configuration. No VPN configuration, host key or user SSH key is regenerated by this feature.