SSH prints this when the server declines to allocate a pseudo-terminal for an interactive session. The usual cause is a restricted key or sshd policy that forbids a TTY, not a broken server.
A PTY (pseudo-terminal) is the virtual terminal SSH allocates so you can run an interactive shell. The message 'PTY allocation request failed on channel 0' means your client asked for a TTY (the default when you run `ssh host` with no command, or when you pass `-t`) and the server refused to grant one. In the overwhelming majority of cases this is intentional, not a fault. The key you authenticated with is restricted in the server's `~/.ssh/authorized_keys` (a `command="..."` forced command, the `no-pty` option, or `restrict`), or the server's `sshd_config` sets `PermitTTY no`, a `ForceCommand`, or a `Match` block that disables TTYs. These are standard for deploy/backup keys and Git hosting (GitLab, Gitea, GitHub) where only specific commands are allowed and an interactive shell is deliberately blocked. It is almost never PTY exhaustion or a missing `/dev/pts` on a normal host. Those exist but are rare and must be diagnosed, not assumed. The warning is non-fatal: if the channel only needed to run a command, it still runs; only the interactive terminal is missing.
Many SSH uses do not need an interactive terminal. If you only run a single command or pipe data, request no TTY with -T so the server has nothing to refuse:
ssh -T user@hostname 'uname -a'The -T flag disables the TTY request; -t forces one. Be honest with yourself about which you need:
- If you only need to run a command, -T makes the warning disappear and the command runs.
- If you genuinely need an interactive shell (a prompt, top, vim, etc.), -T does NOT fix anything — it just stops asking for the TTY the server is refusing. You still get no shell. In that case the server policy is the real problem; continue below.
Note: Git over SSH and SFTP do not request a PTY, so they never produce this warning. If those fail, the cause is something else (auth, host key, path), not PTY allocation.
The refusal is almost always tied to the specific key the server accepted. Find out which one with verbose output:
ssh -v user@hostname 2>&1 | grep -i 'Offering\|Server accepts\|Authentications'Look for the line Server accepts key: ... and note the path of the matching private key (often ~/.ssh/id_ed25519). You will check this key's entry on the server next. If you use an agent, ssh-add -l lists loaded keys.
This is the leading cause. On the server (or ask the server admin), look at the authorized_keys for the target account and find the line matching your public key:
cat ~/.ssh/authorized_keysA restricted entry looks like one of these, with options BEFORE the key type:
command="/usr/bin/backup-only",no-pty ssh-ed25519 AAAA... deploy@ci
restrict ssh-ed25519 AAAA... ci-key
no-pty,no-X11-forwarding ssh-ed25519 AAAA... readonly- no-pty explicitly forbids a TTY.
- restrict enables all restrictions, including no-pty, unless re-enabled with pty.
- command="..." forces a fixed command; an interactive shell is impossible regardless.
If this restriction is intentional (deploy/backup/Git key), it is working as designed — do not remove it just to get a shell. Use a different, unrestricted key or account for interactive access. If a TTY is genuinely required and authorized, the admin can add the pty option (and remove no-pty/forced command) for that line, then have you reconnect. Changing authorized_keys does not require restarting sshd.
If the key is not restricted, the daemon policy may be. On the server inspect the effective config:
sudo sshd -T -C user=youruser,host=$(hostname),addr=127.0.0.1 2>/dev/null | grep -iE 'permittty|forcecommand'
sudo grep -inE 'permittty|forcecommand|^match' /etc/ssh/sshd_config /etc/ssh/sshd_config.d/*.conf 2>/dev/null- PermitTTY no disables TTY allocation. The default is yes.
- ForceCommand ... runs a fixed command instead of your shell, which also blocks an interactive session.
- A Match User, Match Group, or Match Address block can set either of the above only for certain users or sources, which is why some users get a shell and others do not.
If the restriction is intentional, leave it. If a TTY should be allowed, the admin edits the relevant block (or Match section) to PermitTTY yes and removes the blocking ForceCommand, validates with sudo sshd -t, then reloads:
sudo sshd -t && sudo systemctl reload ssh # or: sudo systemctl reload sshdReload (not restart) keeps existing sessions alive.
If the target is a container, pod, or appliance that intentionally only allows specific commands, do not fight the SSH policy — use the platform's own interactive entry point:
# Docker
docker exec -it <container> /bin/bash
# Kubernetes
kubectl exec -it <pod> -- /bin/sh
# Cloud VM with no interactive SSH
# use the provider's serial/web consoleThese give you a real TTY without relying on the restricted SSH path.
These are rare and should only be checked after ruling out key and sshd policy. Diagnose first — do NOT remount or kill sessions on a live, multi-user host, as umount /dev/pts breaks every active terminal and can wedge logins.
Check the real PTY limit and current usage (modern Linux uses Unix98 PTYs; the default max is around 4096, not 256):
cat /proc/sys/kernel/pty/max # configured maximum
cat /proc/sys/kernel/pty/nr # currently allocatedIf nr is close to max, you are genuinely out of PTYs; raise the limit deliberately (e.g. sysctl -w kernel.pty.max=8192) and investigate what is leaking terminals rather than mass-killing sessions.
On a broken/minimal container only, confirm devpts is present:
mount | grep devpts
ls -la /dev/ptsIf it is missing inside an isolated container you control (not a shared host), it can be mounted with mount -t devpts devpts /dev/pts. Never unmount devpts on a host with active sessions.
PTY allocation is requested automatically when you start an interactive login (ssh host with no command) and explicitly when you pass -t; passing -T suppresses it. Because the request travels over an already-authenticated channel, a refusal is a policy decision by the server, not a transport failure — which is why inspecting authorized_keys and the effective sshd -T output is far more productive than poking at /dev/pts.
Git hosting platforms rely on this deliberately: their keys carry command="..." plus no-pty/restrict, so an interactive shell is impossible and a forced ssh -t will always print this warning. That is correct, secure behavior, not a bug to work around.
On systemd hosts, /dev/pts is managed by devtmpfs and is essentially always mounted; manual remounting on a running multi-user host is almost never needed and is dangerous. Treat a missing devpts as a symptom of a broken container image, not a routine fix. The legacy '256 PTY limit' figure refers to old BSD-style PTYs; modern Linux Unix98 PTYs are bounded by /proc/sys/kernel/pty/max, commonly ~4096.
sign_and_send_pubkey: no mutual signature supported
How to fix "sign_and_send_pubkey: no mutual signature supported" in SSH
Someone could be eavesdropping on you right now (man-in-the-middle attack)!
How to fix SSH man-in-the-middle attack warning in SSH
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @ WARNING: UNPROTECTED PRIVATE KEY FILE! @ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
How to fix "WARNING: UNPROTECTED PRIVATE KEY FILE!" in SSH
sign_and_send_pubkey: signing failed for RSA from agent: agent refused operation
How to fix "sign_and_send_pubkey: signing failed for RSA from agent: agent refused operation" in SSH
Bad owner or permissions on /home/user/.ssh/known_hosts
How to fix "Bad owner or permissions on known_hosts" in SSH