Docs / Help
Troubleshooting
Most connection problems come down to one of a handful of causes — and almost all of them are fixable from your side in under a minute once you know what the message means.
NetShell is a free SSH client for iPhone, iPad & Mac, and it deliberately fails closed: when something is wrong, it stops rather than quietly doing the unsafe thing. That means an error is usually NetShell protecting you, not breaking. Work through the relevant section below — each one explains what the symptom means and exactly what to change.
1. "Connection refused" or the connection times out
These two look similar but mean different things. Connection refused means the server answered but nothing is listening on the port you tried. Timeout means nothing answered at all — the packets went into a void.
- Check the host and port. The default SSH port is
22. If your server runs SSH on a non-standard port, set it explicitly in the connection's Port field. A wrong port is the most common cause of "refused". - Confirm the SSH daemon is running on the server (
sudo systemctl status sshon most Linux distros). - Timeouts usually mean a firewall or routing problem — a cloud security group,
ufw, or the device not being on the same network/VPN as the server. - Verify reachability first. Use the network scanner on the same network; it does a Bonjour + port scan and flags which hosts actually have an SSH server listening. If the scanner can't see it, NetShell can't connect to it.
2. "Authentication failed" / permission denied
The server was reached and identified itself correctly, but it rejected your credentials. The handshake worked; the login didn't.
- Re-check the username. SSH usernames are case-sensitive and are separate from the hostname.
ubuntu,root, andadminare common but server-specific. - Password vs. key. Confirm whether the server expects a password or a key. If the server has
PasswordAuthentication no, a password will always be refused — you must use a key. - Wrong key selected. In the connection's settings, make sure the chosen key from your Key Vault is the one whose public half is in the server's
~/.ssh/authorized_keys. - Account locked or expired on the server side will also surface here — check server logs (
journalctl -u ssh).
3. "Host key has changed" warning
This is one to take seriously. NetShell pins each server's host key the first time you connect (trust-on-first-use) and verifies it on every later connection. A changed key means the machine answering is presenting different identity proof than before.
- Benign causes: the server was rebuilt, reinstalled, or an administrator deliberately rotated the host key.
- Dangerous cause: a man-in-the-middle attacker substituting their own key to intercept your traffic.
NetShell can't tell these apart, so it blocks the connection and hands the decision to you — and crucially, it does this at handshake time, so no password or key signature is ever sent to the changed host. Verify the change is expected (ask whoever runs the box, or compare the fingerprint on its console) before approving the new key. If you weren't expecting a change, treat it as hostile. See Host verification for the full model.
4. The key isn't accepted by the server
You picked the right key but the server still won't let it in. This is almost always a server-side configuration detail, not a NetShell bug.
- Public key not installed. Copy your key's public half (export it from the Key Vault) into the target account's
~/.ssh/authorized_keys, one key per line. - Permissions too open. SSH refuses keys when permissions are loose. On the server:
chmod 700 ~/.ssh && chmod 600 ~/.ssh/authorized_keys. - Wrong key type. NetShell generates and imports ed25519 and RSA keys (encrypted ed25519/RSA imports are supported). Make sure the public key you installed matches the private key selected.
- Encrypted key passphrase. If your imported key is passphrase-protected, NetShell will need that passphrase; an incorrect one looks like a rejected key.
More detail in SSH keys and Importing hosts & keys.
5. "Permission denied" in the SFTP browser
You can connect to the terminal but the SFTP browser can't open a folder or upload a file. SFTP runs as your SSH user and obeys exactly that user's filesystem permissions.
- The user doesn't own the path. You can only read/write where your account has rights — system directories owned by
rootwill be denied. - Read-only mount or full disk. Writes fail if the target filesystem is read-only or out of space (
df -hon the server). - Fix permissions or use a path you own, such as your home directory, then move files server-side with the terminal if needed.
6. Docker containers aren't showing up
The Docker manager talks to the Docker daemon over your existing SSH session, so a blank list usually means the SSH user can't reach the daemon.
- Docker isn't installed or running on that host — check with
docker psin the NetShell terminal. - The SSH user lacks Docker access. If
docker psworks only withsudo, add the user to thedockergroup (sudo usermod -aG docker $USER) and reconnect. - No containers exist yet — an empty list is correct if nothing is running. Start a container or Compose stack and refresh.
docker ps returns results in the terminal but the Docker tab is empty, disconnect and reconnect so NetShell re-reads the daemon over a fresh session.7. The AI assistant returns errors
NetShell's AI runs one of two ways: on-device with Apple Intelligence, or with a model you bring yourself. The fix depends on which you're using.
- Apple Intelligence. This needs a supported device on iOS 26+ with Apple Intelligence enabled in iOS Settings. On older OS versions or unsupported hardware it simply isn't available — switch to a bring-your-own model instead. See Apple Intelligence.
- Bring your own model (Claude, OpenAI, Ollama). Errors here are usually a bad or missing API key, an out-of-credit account, or a wrong endpoint URL. Re-paste the key, confirm the account has quota, and for a self-hosted Ollama make sure the device can actually reach its address. See Bring your own model.
8. Face ID isn't prompting
NetShell protects your keys and reseals the app behind Face ID. If the prompt never appears, it's typically an OS-level permission.
- Face ID permission for NetShell may be off — check iOS Settings → Face ID & Passcode → Other Apps, and your device's Settings entry for NetShell.
- No device passcode set. Biometric protection requires a passcode; without one, the hardware-backed iOS Keychain can't gate access. Set a passcode in iOS Settings.
- Face ID failing repeatedly falls back to your device passcode — that's expected behaviour, not a failure.
Details in Face ID lock.
9. Connections (or keys) don't appear on another device
NetShell syncs through iCloud, and the two halves travel by different paths — so a partial sync is a useful clue.
- Connections, snippets, folders, groups, and tags sync via iCloud key-value storage.
- Passwords and private keys sync only through Apple's end-to-end encrypted iCloud Keychain — never through a NetShell server.
- Host (known-hosts) keys never sync — they stay device-local by design, so each device approves new hosts on first use.
If nothing appears: confirm both devices are signed into the same Apple ID, that iCloud Drive and iCloud Keychain are both enabled in iOS Settings, and that the devices have network access. iCloud sync is not instant — give it a minute and reopen the app. See Syncing across devices and iCloud Keychain sync.
10. The app re-locks too often
NetShell auto-relocks behind Face ID after the app has been idle, which is a security feature — but the timing is yours to adjust. If it's locking sooner than you'd like, lengthen the idle timeout in NetShell's security settings. If it's locking less than you'd like, shorten it. Remember that switching to another app, then back, can trigger a re-lock once the idle window has elapsed; that's working as intended. See Face ID lock to tune it.
11. A command was blocked before it ran
If a command never reached the server, NetShell's destructive-command guard may have intercepted it. The guard stops genuinely dangerous lines — rm -rf, DROP TABLE / TRUNCATE TABLE, git push --force, git reset --hard, shutdown/reboot, kubectl delete namespace, helm uninstall, piping a download straight to bash, and similar — before they hit the wire. If you genuinely intend the action, confirm the prompt; otherwise this just saved you. See Command guard.
Still stuck?
Work top to bottom: can the network scanner see the host (reachability), does the handshake succeed (host verification), and does login succeed (credentials)? Isolating which of those three stages fails points straight at the fix. The FAQ covers more general questions, and you can grab the latest build any time — download NetShell on the App Store.