Overview
meshTerm is an SSH terminal client for iPhone and iPad. It lets you connect to remote servers using password or SSH key authentication, and integrates with Tailscale to browse and connect to your Tailnet devices directly from the app.
Prerequisites
For all connections
- A server with SSH enabled and accessible from your device
- Your server's hostname or IP address, port, and a valid username
For password authentication
- The password for your server account
For SSH key authentication Pro
- An Ed25519 SSH key pair. You can generate one inside meshTerm, or bring your own unencrypted OpenSSH key.
- The corresponding public key added to
~/.ssh/authorized_keyson the server
For Tailscale SSH Pro
- Tailscale app installed on your iPhone/iPad — meshTerm routes connections through the Tailscale VPN tunnel, which requires the Tailscale app to be running and connected
- Both your iPhone and the target server must be on the same Tailnet
- The server must have Tailscale SSH enabled in your Tailnet ACLs
For Tailscale device browsing Pro
- A Tailscale API token (read-only) — see Getting a Tailscale API Token
- The Tailscale app installed and connected to your Tailnet
Getting Started
Adding your first host
- Open meshTerm. You will see the host list (empty on first launch).
- Tap + in the top-right corner.
- Fill in the connection details:
- Label — a friendly name for this connection (e.g. "My Server")
- Hostname or IP — the address of your server
- Port — defaults to 22
- Username — your account name on the server
- Under Authentication, choose a method and enter your credentials.
- Tap Add to save.
Connecting
Tap any host in the list to open a terminal session. meshTerm connects immediately — you will see a "Connecting…" indicator while the session is being established.
Managing SSH Hosts
Editing a host
Swipe right on a host and tap Edit, or long-press the row to reveal options.
Deleting a host
Swipe left on a host and tap Delete.
Host limit
Free accounts can save 1 host. meshTerm Pro removes this limit.
Connecting to a Host
When you tap a host, meshTerm:
- Resolves the hostname and opens a TCP connection to the server.
- Verifies the server's host key against your saved known hosts (see Known Hosts).
- Authenticates using the method configured for that host.
- Requests a PTY and launches a shell session.
The terminal becomes interactive as soon as the shell is ready.
Environment variables
You can attach custom environment variables to any host. These are sent to the shell session on connect. To add them, edit the host and use the Environment Variables section.
Disconnecting
Close the terminal view or terminate the shell session from the server side (e.g. exit, logout, or Ctrl+D).
Authentication Methods
Password
Enter your password when adding or editing the host. Passwords are stored securely in the iOS Keychain and never written to disk in plain text.
SSH Key Pro
Select one of your saved SSH keys when adding or editing the host. The private key never leaves your device — meshTerm signs the authentication challenge locally and sends only the public key to the server.
To use SSH key authentication:
- Generate or import a key in Settings → SSH Keys (see SSH Key Management).
- Copy the public key and add it to
~/.ssh/authorized_keyson your server. - When adding or editing a host, set the auth method to SSH Key and select the key.
Tailscale SSH Pro
For servers on your Tailnet with Tailscale SSH enabled, no password or key is required. Tailscale authenticates the connection at the network layer using your device's Tailscale identity.
Requirements:
- Tailscale app installed and connected on your iPhone/iPad
- Server enrolled in the same Tailnet with Tailscale SSH enabled in ACLs
- On the remote host:
sudo tailscale up --ssh
Tailscale SSH authentication is handled entirely by the Tailscale app — meshTerm does not send any credentials for these connections.
SSH Key Management
Access SSH keys via Settings → SSH Keys.
Generating a new key
Generating a key is a two-step process. First, the key is created and saved; then you have the option to install it on a host without leaving the sheet.
- Tap Add Key.
- Enter a label (e.g. "Work iPhone").
- Tap Generate. meshTerm creates a new Ed25519 key pair, saves it securely in the iOS Keychain, and keeps the sheet open.
The public key is shown in the key list in OpenSSH format:
ssh-ed25519 AAAA... Work iPhone
The comment at the end reflects the label you gave the key. Tap Done to close the sheet at any time.
Installing a key on a host
If you have any saved hosts, an Install on a Host section appears on the sheet immediately after the key is generated. This lets you push the public key to a host in one step — no manual copy-and-paste into authorized_keys required.
- In the Install on a Host section, select a host from the picker.
- Tap Install Key.
meshTerm opens a non-interactive exec channel to the selected host (no PTY or shell session is started) and appends the public key to ~/.ssh/authorized_keys on the server. The connection uses the credentials already stored for that host.
Known host required. Installation uses strict host key verification — TOFU prompting is not shown during this flow. If the host's key is not yet trusted, a message in the footer will tell you to connect to that host via the terminal first, then return to install the key.
Once the key is installed successfully, the status updates in the sheet. Tap Done to dismiss.
Importing an existing key
- Tap Add Key → Import.
- Paste your unencrypted OpenSSH private key (the full contents of the file, including the
-----BEGIN OPENSSH PRIVATE KEY-----and-----END OPENSSH PRIVATE KEY-----lines). - Tap Import.
Requirements for import:
- Ed25519 keys only
- Unencrypted (no passphrase). To strip a passphrase:
ssh-keygen -p -N "" -f ~/.ssh/id_ed25519
Copying a public key
Tap the copy icon next to a key to copy the full OpenSSH public key to your clipboard. Paste this into ~/.ssh/authorized_keys on your server.
Deleting a key
Swipe left on a key and tap Delete. The private key is permanently removed from the Keychain.
If you delete a key that is assigned to a host, that host will fail to connect until you edit it and assign a different key.
Key storage
- Private keys are stored as 32-byte Ed25519 seeds in the iOS Keychain, protected at rest by the device's secure enclave.
- Private keys are marked
WhenUnlockedThisDeviceOnly— they cannot be backed up to iCloud or moved to another device. - Public keys are stored in UserDefaults for display purposes only.
Tailscale Integration
meshTerm integrates with the Tailscale VPN to let you browse your Tailnet and add devices directly as SSH hosts.
Prerequisites
- meshTerm Pro
- Tailscale app installed and connected to your Tailnet
- A read-only Tailscale API token (see below)
Getting a Tailscale API Token
In meshTerm, tap Settings → Tailscale → How to get an API token for in-app instructions. The steps are:
- Go to tailscale.com and sign in.
- Navigate to Settings → Personal Settings → Keys.
- Under API Access Tokens, click Generate token.
- Give the token a label (e.g. "meshTerm").
- Set an expiry — 90 days is recommended.
- Leave permissions as read-only (meshTerm does not need write access).
- Copy the token.
- In meshTerm, go to Settings → Tailscale → API Token and paste it in.
Your API token is stored securely in the iOS Keychain. meshTerm uses it only to fetch your device list and never modifies your Tailnet configuration.
Browsing your Tailnet
- Tap the globe icon in the host list toolbar.
- Your Tailnet devices are listed with their hostname, IP address, and operating system.
- Enter a username (applied to all devices added in this session).
- Tap + next to a device to add it as an SSH host.
Devices added from the Tailnet browser are automatically configured to use Tailscale SSH auth (if you are on Pro).
API token expiry
Tailscale API tokens expire. When your token expires, the Tailnet browser will show an error. Return to Settings → Tailscale and generate a new token using the steps above.
Snippet Vault
The Snippet Vault (Pro) is a searchable library of terminal commands you can send to the active session with a single tap.
Access it from the snippets button in the terminal toolbar.
Default snippets
meshTerm ships with two folders of pre-loaded snippets:
Linux — common admin commands including ls -lah, df -h, ps aux, ss -tuln, tail -f /var/log/syslog, systemctl status, and more.
OpenClaw — commands for OpenClaw including openclaw update, openclaw doctor, openclaw models list, openclaw gateway status, and openclaw memory index --force.
Using a snippet
Tap any snippet to send the command text directly to the terminal. The Vault closes automatically and the command is typed into your active session.
Adding snippets
- Tap + in the Snippet Vault toolbar.
- Enter a title and the command text.
- Optionally assign it to a folder and add tags.
- Tap Save.
Searching
Use the search bar at the top of the Vault. meshTerm searches across snippet titles, command text, and tags.
Folders
Tap New Folder to organise snippets. Tap a folder to view only its snippets. Deleting a folder does not delete its snippets — they move to the root level.
Terminal Controls
Modifier keys
| Key | Description |
|---|---|
| Ctrl | One-shot Ctrl modifier. Tap once, then press a key (e.g. C, D, Z, L). Releases automatically after one keystroke. |
| Esc | Sends the Escape character. Use to exit insert mode in vim or cancel prompts. |
| Alt | One-shot Alt/Meta modifier. Use for word navigation: Alt+F (forward word), Alt+B (back word). |
| Tab | Sends Tab for shell autocompletion. |
Common Ctrl sequences
| Sequence | Action |
|---|---|
| Ctrl + C | Interrupt — stop the running command |
| Ctrl + D | End of input — log out or close session |
| Ctrl + Z | Suspend — background the current process |
| Ctrl + L | Clear — redraw the screen |
| Ctrl + A | Move cursor to beginning of line |
| Ctrl + E | Move cursor to end of line |
| Ctrl + R | Reverse history search |
| Ctrl + W | Delete the word before the cursor |
Arrow keys
- ↑ / ↓ — Navigate command history; move cursor in full-screen apps (vim, htop)
- ← / → — Move cursor; scroll through menus in full-screen apps
Extended keys
Tap the keyboard dismiss button to reveal the full extended key row:
- F1–F12 — Function keys
- Home / End — Jump to start/end of line
- Page Up / Page Down — Scroll one screen at a time
Symbol strip
The symbol strip provides quick access to commonly used characters:
| ` ~ $ / \ { } [ ]
Security
Known Hosts (TOFU)
meshTerm uses Trust On First Use (TOFU) to verify server identity. The first time you connect to a host, meshTerm presents the server's host key fingerprint and asks you to confirm before proceeding.
- Tap Trust & Connect to accept the fingerprint and save it.
- Tap Cancel to abort the connection.
On subsequent connections, meshTerm checks the fingerprint automatically. If it has changed, the connection is blocked with a security warning (see Host key mismatch).
Viewing and managing known hosts
Go to Settings → Known Hosts to see all trusted hosts. Swipe left on an entry to delete it.
If a server's host key legitimately changes (e.g. after a rebuild), delete the old entry from Known Hosts and reconnect to accept the new fingerprint.
Credential storage
All sensitive data is stored in the iOS Keychain:
- SSH private keys
- SSH passwords
- Tailscale API tokens
Nothing sensitive is written to iCloud backup, UserDefaults, or the filesystem.
App Lock
meshTerm can be locked with Face ID, Touch ID, or your device passcode. When enabled, the app locks automatically when it moves to the background and requires biometric or passcode authentication to reopen.
Enable app lock in Settings → App Lock.
App Lock requires a device passcode to be set. If no passcode is configured, you will be prompted to set one in iOS Settings → Face ID & Passcode.
Settings
SSH Keys
Manage your SSH key pairs. See SSH Key Management.
Security → Known Hosts
View and delete trusted host fingerprints. See Known Hosts.
Tailscale → API Token
Enter your read-only Tailscale API token to enable Tailnet device browsing. See Tailscale Integration.
About
Shows the current app version and links to the Privacy Policy and Terms of Use.
meshTerm Pro
meshTerm Pro unlocks the following features:
| Feature | Free | Pro |
|---|---|---|
| Saved hosts | 1 | Unlimited |
| Password authentication | Yes | Yes |
| SSH key authentication | — | Yes |
| Generate / import SSH keys | — | Yes |
| Tailscale SSH | — | Yes |
| Tailscale device browsing | — | Yes |
| Snippet Vault | — | Yes |
| Known hosts management | Yes | Yes |
| Terminal emulation | Yes | Yes |
| App Lock | Yes | Yes |
Subscribing
Tap Upgrade in Settings or the paywall prompt. Pro is available as a monthly or annual subscription — the annual plan is the best value.
Restoring purchases
Tap Restore Purchases in Settings if you reinstall the app or switch devices.
Troubleshooting
Connection issues
"Could not resolve '[hostname]'"
The device cannot look up the hostname via DNS.
- Check the hostname is spelled correctly.
- Check your device has a working internet connection.
- If using a local hostname (e.g.
myserver.local), ensure you are on the same local network.
"Could not connect to [host]:[port]"
The TCP connection was refused or timed out.
- Verify the server is online and accessible.
- Check the port number is correct (default SSH is 22).
- Confirm SSH is running on the server:
sudo systemctl status ssh. - If connecting to a local network address, ensure meshTerm has Local Network permission: go to iOS Settings → Privacy & Security → Local Network and enable meshTerm.
"The connection was closed"
The server terminated the session.
- The server may have timed out an idle connection. Reconnect and consider setting
ClientAliveIntervalon the server. - The shell may have exited normally (e.g. you typed
exit).
Connection hangs at "Connecting…"
- Check your network connection.
- If connecting via Tailscale, ensure the Tailscale app is open and connected to your Tailnet.
- Try toggling Tailscale off and on.
Authentication issues
"No SSH key selected. Edit the host and choose a key."
The host is set to SSH key authentication but no key has been assigned.
- Go to the host list, swipe left on the host, and tap Edit.
- Under Authentication, select a key from the Key picker.
- If no keys are listed, go to Settings → SSH Keys and generate or import one first.
SSH key auth fails silently or server rejects key
- Confirm the public key is in
~/.ssh/authorized_keyson the server. - Ensure the
~/.sshdirectory has permissions700and~/.ssh/authorized_keyshas permissions600on the server. - Check
sshd_configon the server hasPubkeyAuthentication yes.
Password auth fails
- Double-check the username and password.
- The server may require key-based auth only. Check
/etc/ssh/sshd_configforPasswordAuthentication no.
Tailscale issues
"Enter your Tailscale API token in Settings first."
You opened the Tailnet browser without an API token configured.
- Go to Settings → Tailscale → API Token and paste in a valid token.
- See Getting a Tailscale API Token for how to generate one.
"Invalid or expired token."
Your API token has expired or is invalid.
- Go to tailscale.com → Settings → Personal Settings → Keys and generate a new token.
- Paste the new token into Settings → Tailscale → API Token.
Tailnet devices are missing from the browser
- Only authorised devices appear in the browser. Check your Tailnet's device authorisation settings.
- Confirm the API token was generated for the correct Tailnet account.
- Try pulling to refresh the device list.
Tailscale SSH connection fails
- Confirm the Tailscale app is installed, open, and connected to your Tailnet.
- Confirm the target device is online in your Tailnet (visible in the Tailscale admin console).
- Confirm Tailscale SSH is enabled in your Tailnet ACLs for the target device. See Tailscale SSH docs.
- Both your iPhone and the server must be on the same Tailnet.
Security warnings
Host key mismatch
⚠ Host key mismatch for [hostname]!
Stored: [expected fingerprint]
Received: [actual fingerprint]
The server's host key has changed since you last connected. This can indicate:
- Legitimate change: the server was rebuilt or its SSH keys were regenerated.
- Security issue: a man-in-the-middle attack.
If you are confident the key change is legitimate:
- Go to Settings → Known Hosts.
- Find the entry for the affected host and swipe left to delete it.
- Reconnect — you will be prompted to trust the new fingerprint.
If you are not sure, do not connect and investigate the server directly.
Key installation issues
"Connect via the terminal first to trust this host."
The host's key is not yet in your known hosts store. The Install on a Host flow uses strict verification and will not prompt you to trust an unknown host.
- Tap the host in the main host list to open a normal terminal session.
- Accept the host key fingerprint when prompted.
- Return to Settings → SSH Keys, tap the key, and use Install on a Host again.
Installation fails with an authentication error
- The credentials stored for the selected host may be incorrect or the account may not have permission to write to
~/.ssh/authorized_keys. - Try connecting to the host via the terminal to confirm the credentials work, then retry the installation.
Key appears to install but authentication still fails
- Confirm the
~/.sshdirectory has permissions700and~/.ssh/authorized_keyshas permissions600on the server. - Check that
PubkeyAuthentication yesis set in/etc/ssh/sshd_configon the server. - If the file had incorrect permissions before installation, correct them and reconnect.
SSH key import errors
"The key format is not recognised."
- Ensure you are pasting the entire private key file, including the
-----BEGIN OPENSSH PRIVATE KEY-----and-----END OPENSSH PRIVATE KEY-----header and footer lines. - The key must be in OpenSSH format, not PEM/PKCS8. To convert:
ssh-keygen -t ed25519 -m OpenSSH.
"Encrypted (passphrase-protected) keys are not supported."
meshTerm does not support passphrase-protected keys. To remove the passphrase from an existing key:
ssh-keygen -p -N "" -f ~/.ssh/id_ed25519
"Unsupported key type. Only Ed25519 keys are supported."
meshTerm supports Ed25519 keys only. To generate a compatible key:
ssh-keygen -t ed25519 -C "your label"
App Lock issues
"meshTerm requires a device passcode to protect your SSH credentials."
App Lock requires a device passcode to be set before it can be enabled.
- Go to iOS Settings → Face ID & Passcode and set up a passcode.
- Return to meshTerm and enable App Lock in Settings.
Snippet Vault
Snippets are not sent to the terminal
- Ensure you have an active terminal session open before opening the Snippet Vault.
- If the session was disconnected, reconnect and try again.
Purchases
"Purchase could not be verified."
There was a problem verifying your purchase with the App Store.
- Ensure your device has a working internet connection.
- Try Restore Purchases in Settings.
- If the issue persists, contact Apple Support via the App Store.
meshTerm is developed by James Betchley. For support or feedback, please open an issue on GitHub.