Files
2026-07-12 10:17:17 -04:00

2.8 KiB

Sudo TTY Workaround for SSH Commands

When sudo requires a TTY (requiretty in sudoers) and you're running commands via SSH without a pseudo-terminal, sudo refuses even with NOPASSWD set. On newer sudo versions (Ubuntu 26.04+), Defaults:user !requiretty is not a valid setting and will cause a parse error.

The Problem

ssh user@host 'sudo whoami'
# → sudo: a terminal is required to authenticate

Even if /etc/sudoers.d/user contains user ALL=(ALL) NOPASSWD: ALL, the requiretty flag in the main sudoers file still blocks non-TTY commands.

The Solution: Python PTY Fork

Use Python's pty module to fork a child with a proper TTY, write to its stdin, and collect the result:

import pty, os

pid, fd = pty.fork()
if pid == 0:
    # child — executes the sudo command with a real TTY
    os.execvp("sudo", ["sudo", "tee", "/etc/sudoers.d/ray"])
else:
    # parent — sends input to the child's TTY
    os.write(fd, b"<password>\n")
    os.write(fd, b"ray ALL=(ALL) NOPASSWD: ALL\n")
    os.close(fd)
    os.waitpid(pid, 0)
    print("DONE")

However, this approach is fragile — os.write() to a PTY doesn't guarantee the sudo process reads the password before the content. It may print "DONE" without actually writing the file.

The Reliable Solution: Python subprocess with sudo -S

Run this directly on the remote machine via SSH (NOT piped through the terminal tool's sudo filter):

ssh user@host 'python3 -c "
import subprocess
r = subprocess.run([\"sudo\", \"-S\", \"tee\", \"/etc/sudoers.d/ray\"],
    input=b\"<password>\\nray ALL=(ALL) NOPASSWD: ALL\\n\",
    capture_output=True, timeout=10)
print(\"RC:\", r.returncode)
"'

This works because sudo -S reads the password from stdin, and subprocess.run() with input= pipes it to the child process. The capture_output=True captures any password prompts.

Why Other Approaches Don't Work

Approach Result
echo 'nopasswd' | sudo tee file Fails — requires TTY
script -qc "sudo tee file" /dev/null Prompts for password interactively, hangs
ssh -tt user@host 'sudo ...' Opens PTY but prompts for password, SSH tool blocks sudo -S
Default:user !requiretty Not a valid setting in sudo 1.9.x+ (Ubuntu 26.04)

Verification

After creating the sudoers file:

sudo -n whoami
# → root

The -n (non-interactive) flag ensures sudo won't prompt for a password. If it returns root, passwordless sudo is working.

Cleanup on Ubuntu 26.04+

If you accidentally added Defaults:user !requiretty:

sudo sed -i "/requiretty/d" /etc/sudoers.d/ray
sudo visudo -c -f /etc/sudoers.d/ray

The requiretty flag was removed from sudo's parser in newer versions (saw this on Ubuntu 26.04 with sudo 1.9.x+). It causes: unknown setting: 'requiretty'.