I recently encountered unexpected authentication behavior on Debian 12 (Bookworm): the Cockpit web interface refused direct root login attempts with the root user.
At first glance, the common fix seems obvious: open /etc/cockpit/disallowed-users and remove root from the blacklist. However, even after editing the file and restarting the services, the web interface continued returning authentication failure errors.
When the web UI fails without clear error messages, the real solution requires looking deeper into OS-level components: understanding how PAM, systemd-logind, Shadow/Shell records, and Polkit interact on Debian.
Here is the complete diagnostic breakdown and the practical steps to resolve access.
1. Diagnostic: why removing root from the blacklist was not enough#
Cockpit does not handle password validation on its own; it delegates authentication to the underlying operating system through cockpit-ws, cockpit-session, and cockpit-bridge. Blocking the root user happens across multiple layers:
[ Web Browser ]
│
▼
[ cockpit-ws ] ──── Query ───► /etc/cockpit/disallowed-users
│
▼
[ PAM Stack (/etc/pam.d/cockpit) ] ───► pam_listfile.so / common-auth
│
▼
[ OS Subsystems ] ───► /etc/shadow (Hashes/Locks) & /etc/passwd (Valid Shell)
The PAM stack (/etc/pam.d/cockpit)#
Even when the web daemon allows the username through, the Cockpit PAM module enforces restrictions via pam_listfile.so:
auth required pam_listfile.so item=user sense=deny file=/etc/cockpit/disallowed-users onerr=succeed
Any mismatch in the inherited common-auth rules or console restrictions causes PAM to return PAM_AUTH_ERR.
Account status in shadow (/etc/shadow) and shell#
In many Debian 12 cloud images (especially installations designed around sudo), the root account has no password set or remains in a locked state (prefixed with ! or * in /etc/shadow). Furthermore, the login shell in /etc/passwd must be a valid executable binary (such as /bin/bash or /bin/sh).
To set a valid password hash:
sudo passwd root
2. Debugging logs and system calls#
To pinpoint the exact failure point, I inspected the authentication logs and system calls generated during login.
Real-time log monitoring#
Tracking services tied to systemd reveals the exact PAM return code:
journalctl -f -u cockpit -u systemd-logind
- If logs report
pam_unix(cockpit:auth): authentication failure, the shadow hash or PAM rule rejected the session. - If messages mention
securettyor pseudo-terminals (pts/X), note thatpam_securettyprimarily applies to local/SSH consoles; its presence indicates inherited rules interfering with the session layer.
Tracing system calls with strace#
Attaching strace to the Cockpit Web Service process allows tracking configuration files accessed during authentication:
strace -f -p $(pgrep cockpit-ws) -e openat,access,connect 2>&1 | grep -E "shadow|pam|disallowed"
After updating configuration files, reload the service sockets:
systemctl restart cockpit.socket cockpit.service
3. Recommended approach: dedicated admin user with polkit elevation#
Logging directly into web dashboards using the root account is generally discouraged for auditability. Cockpit is built from the ground up to allow standard users to authenticate unprivileged and elevate permissions on demand through Polkit and Sudoers.
Step 1: Creating a dedicated local user#
Use adduser to generate the home directory (/home/percio), standard skeleton files, and default permissions:
adduser percio
The system assigns the next available UID (>= 1000), adds the entry to /etc/passwd, and stores the encrypted hash in /etc/shadow.
Step 2: Granting sudo privileges#
Assign administrative privileges:
usermod -aG sudo percio
Why does this resolve cockpit authentication?#
- The user
perciois not present in/etc/cockpit/disallowed-users. - The
cockpit-bridgespawns the initial session as an unprivileged user. - Default Polkit and Sudoers policies permit privilege elevation.
- Inside the web interface, Cockpit displays the "Turn on administrative access" toggle, allowing secure root operations.
Alternative method: assigning UID 0 (root alias)#
You can also assign UID 0 directly to a user account, mirroring root at the Kernel level:
usermod -u 0 -g 0 -o percio
-u 0: Sets User ID to 0.-g 0: Sets primary Group ID to 0.-o: Allows non-unique duplicate UID.
Warning: While providing full system access, this technique disrupts audit trails (auditdandsystemd-journal) and overlaps filesystem ownership inside the home directory since the kernel identifies everything as UID 0. Keep this approach strictly as an emergency last resort or technical curiosity.
4. Verification checklist and SSH keys#
To confirm the new user configuration:
# 1. Verify UID, GID, and groups
id percio
# 2. Test command elevation
su - percio -c "sudo whoami"
# Expected output: root
# 3. Check login session status in logind
loginctl user-status percio
If connecting using SSH public keys, ensure proper permissions on .ssh:
mkdir -p /home/percio/.ssh
chmod 700 /home/percio/.ssh
cp /root/.ssh/authorized_keys /home/percio/.ssh/
chown -R percio:percio /home/percio/.ssh
chmod 600 /home/percio/.ssh/authorized_keys
Conclusion: key takeaways and practical summary#
When Cockpit blocks root logins on Debian 12:
- Editing
/etc/cockpit/disallowed-usersis only the first step; verify that the account has a valid password hash in/etc/shadow(passwd root). - The cleanest configuration is creating a dedicated user in the
sudogroup and letting Polkit handle interactive privilege elevation in the Cockpit web interface.
Was this article helpful?
Leave a quick reaction to help prioritize future technical guides:
This post is licensed under CC BY-NC.



Comments
Join the discussion below.
0 comments