Restrict Root Logins with pam_securetty
You will configure a PAM rule that rejects root authentication from terminals not listed as secure, while leaving non-root authentication unaffected. You will also check the module's console exception and keep a rollback copy of the PAM configuration. Allow about 20 minutes, plus time to arrange an already-open root-capable session for recovery.
The route
Jump straight to the step you need, or tick off Done means at the end.
This guide describes the installed Linux-PAM pam_securetty module from package version 1.5.3-5ubuntu5.7. The local manual page is dated 7 May 2023. PAM stacks vary by distribution and service, so treat the example as a controlled pattern to adapt after inspecting your own files.
Security warning
A bad PAM edit can lock root out of a service or console. Do not test this over your only SSH session, and do not close an existing administrative session until a separate login has been verified. The commands that read files are ordinary commands. Editing PAM configuration, creating the securetty file and changing its ownership or mode require elevated privileges.
1. Check the module and the target PAM service
Confirm that the module exists and identify the service whose root logins you intend to restrict. This module only provides the auth type, and the application must supply the PAM_TTY value correctly.
$ dpkg-query -W -f='${Package} ${Version}\n' libpam-modules:amd64
libpam-modules 1.5.3-5ubuntu5.7
$ ls -l /lib/x86_64-linux-gnu/security/pam_securetty.so
-rw-r--r-- 1 root root ... /lib/x86_64-linux-gnu/security/pam_securetty.so
$ sed -n '1,120p' /etc/pam.d/login
The file path can differ on another architecture. If the module is missing, stop and install or repair the package through your normal system-management process. Do not write a guessed module path into a PAM file.
Checkpoint: decide whether the rule belongs in /etc/pam.d/login, a display-manager file, or another service file. Do not add it to every PAM service by copying a line blindly. A service that does not set PAM_TTY correctly cannot be evaluated reliably by this module.
2. Inspect the secure terminal list
pam_securetty first checks /etc/securetty. If that file is absent and the module was built with vendor-directory support, it uses /securetty instead. Each entry names a terminal device without the /dev/ prefix. On this machine both paths are absent, so root logins would not have an ordinary file-based terminal allow-list.
$ for file in /etc/securetty /securetty; do
if test -e "$file"; then
ls -l "$file"
sed -n '1,120p' "$file"
else
printf '%s: absent\n' "$file"
fi
done
/etc/securetty: absent
/securetty: absent
Common entries are host-specific. Use the names reported by your console and login setup rather than copying a random list. For a login on /dev/tty1, the entry is tty1. For a serial device such as /dev/ttyS0, the entry is ttyS0. An SSH session normally has a pseudo-terminal name such as pts/0, but allowing pseudo-terminals would weaken the point of limiting root to physical or otherwise approved devices. Decide that policy explicitly.
3. Create a minimal allow-list
First preserve any existing file, then create the list with root privileges. Replace the sample terminal with a device you have deliberately approved. The command below changes persistent authentication policy, so review the here-document before pressing Enter.
$ sudo install -o root -g root -m 0600 /etc/securetty /etc/securetty.bak 2>/dev/null || true
$ sudo sh -c 'printf "%s\n" tty1 > /etc/securetty'
$ sudo chown root:root /etc/securetty
$ sudo chmod 0600 /etc/securetty
$ sudo sed -n '1,40p' /etc/securetty
tty1
The module rejects the file if it is not a plain file or is world-writable. The restrictive mode above is acceptable and makes accidental edits less likely. The backup command may report nothing when the file did not exist; in that case there is no previous file to restore.
Checkpoint: verify the metadata before connecting the PAM rule:
$ stat -c '%A %U:%G %n' /etc/securetty
-rw------- root:root /etc/securetty
4. Add the rule before sufficient authentication
Make a dated backup of the target PAM service, then edit it as root. The canonical ordering is a required pam_securetty line before any sufficient authentication method. Keep the existing stack and insert only the module line that matches your service.
$ sudo cp -a /etc/pam.d/login /etc/pam.d/login.before-pam-securetty
$ sudoedit /etc/pam.d/login
Place this line before the first sufficient authentication line, and before the normal password module if that is how the service is structured:
auth required pam_securetty.so
To request diagnostics while testing, add the documented option:
auth required pam_securetty.so debug
Use debug temporarily and consult the service's logging destination. It does not make an unauthorised terminal acceptable. The module's noconsole option is a separate, stricter choice: it prevents automatic acceptance of the kernel console when that device is not also listed in the securetty file.
By default, the module also allows root on the console named by the kernel console= command-line setting and on terminals listed by /sys/class/tty/console/active. If your policy requires the file to be the complete allow-list, use:
auth required pam_securetty.so noconsole
Do not select noconsole without confirming that your approved physical console is present in /etc/securetty. Otherwise a recovery path can disappear when the next login is attempted.
5. Test from a second session
Keep the first administrative session open. From the approved terminal, test a root login using the exact service you changed. From a deliberately unapproved terminal, test that root is rejected. Do not use a production password in a pasted command, and do not run a password-testing loop.
A successful module decision means PAM continues authentication for root on an accepted device. A rejected decision returns an authentication error. The result you see can still be affected by later PAM modules, account policy or the service itself, so record the full service log when diagnosing a failure.
$ sudo sshd -t
... no output on success ...
$ sudo journalctl -b --no-pager | grep -i securetty
The sshd -t check only validates SSH daemon syntax; it does not test a PAM login. Use the service's own non-destructive validation where one exists. The journal command is a read-only diagnostic and may show nothing if the module is not logging at the current level.
6. Recover without guessing
If an approved login fails, use the still-open administrative session or the provider's console. Restore the PAM file first, then restore the terminal list if required:
$ sudo cp -a /etc/pam.d/login.before-pam-securetty /etc/pam.d/login
$ sudo cp -a /etc/securetty.bak /etc/securetty
$ sudo chmod 0600 /etc/securetty
$ sudo chown root:root /etc/securetty
If /etc/securetty.bak did not exist because the original file was absent, do not copy it. Remove the new list only after checking that the path is exactly the file you intend to remove:
$ sudo test -f /etc/securetty.bak || sudo rm -- /etc/securetty
That removal is irreversible unless another backup exists. If the module reports a service error, check that the securetty path is readable, a normal file, and not world-writable. If root is rejected, check the PAM_TTY value and the exact terminal name before changing the policy.
Done means
- You identified the exact PAM service and confirmed the installed Linux-PAM package version.
- You chose terminal names deliberately and verified the securetty file as root-owned and not world-writable.
pam_securetty.sois anauth requiredrule before anysufficientauthentication method.- You understood the default kernel-console exception and selected
noconsoleonly when the file must be authoritative. - A second session confirmed the intended result before the original administrative session was closed.
- You kept a tested rollback copy of both the PAM service file and the terminal list.