Creating a user with sudo privileges and no longer working as root
adduser vs useradd, the sudo and wheel groups, editing sudoers safely with visudo and the test that proves you have not locked yourself out before you switch root off.
Right after a server has been provisioned you are root, and root is allowed to do anything without asking. A single typo hits the entire system immediately, and root is the one username every attacker already knows. This guide walks the whole way: create the user, put it into the right group, extend the sudoers configuration, transfer the public key and only switch root off at the very end. The decisive part comes shortly before that end: the proof that you have not locked yourself out.
The reference systems are Debian 13 (trixie), Debian 12 (bookworm), Ubuntu 24.04 LTS and Ubuntu 22.04 LTS. Wherever RHEL-style systems such as AlmaLinux and Rocky Linux differ, it is noted. The commands are written for working as root; as a normal user, prefix every command with sudo. The short version is in the checklist for new root servers, what follows here is the detail.
Before you change anything: your way back
Two changes here can cost you access: the sudoers configuration and, right at the end, root's permission to log in over SSH. A broken sudoers file takes your privileges away, and a root login switched off too early takes away your fallback. So there are three things to settle first.
A second session. Open a second terminal window with an active SSH connection as root and do not close it until everything has been verified. An existing session survives a restart of the SSH service just as it survives a faulty sudoers file.
The route around SSH. On KVM root servers and dedicated servers from KernelHost you open the VNC console in the customer panel. It attaches to the virtualization layer, or to the machine itself, which makes it independent of SSH, the firewall and the sudoers file. Log in there once beforehand: a rescue route you only try out in an emergency is not a rescue route.
A password that you know. The console has no concept of SSH keys, so you log in there with a username and a password, or not at all. This is where most lockouts begin.
Rule of thumb: the rescue route is a console, and a console knows nothing but passwords. Before you switch password authentication off, at least one account has to have a password that you know.
Taking stock: is sudo installed at all?
On Ubuntu server images sudo is present, on minimal Debian images it often is not. Three lines settle the starting position:
command -v sudo || echo "sudo is missing"
getent group sudo
awk -F: '$3 >= 1000 && $3 < 65534 {print $1, $3, $7}' /etc/passwd
The second line shows the group together with its members, the third one shows every regular account with its ID and login shell. On images built with cloud-init there is often an account with sudo privileges already. If sudo is missing, install it:
apt-get update
apt-get install -y sudo
sudo -V | head -n 1
adduser or useradd: two tools, two results
If you reach for useradd while expecting adduser, you end up with an account that has no home directory and a shell you were not counting on.
| Property | adduser | useradd |
|---|---|---|
| Availability | Debian and Ubuntu | everywhere, including RHEL-style systems |
| Operation | interactive, asks for a password and the name fields | does only what the switches say |
| Home directory | created and populated from /etc/skel | only with -m |
| Login shell | from /etc/adduser.conf | from /etc/default/useradd, often /bin/sh |
| Password | prompted for, unless --disabled-password is used | never set |
| On RHEL-style systems | just another name for useradd | the actual tool |
On Debian and Ubuntu, adduser is the right choice:
adduser --disabled-password --gecos "" kernel
--gecos "" skips the questions about names and phone numbers, --disabled-password creates the account without a password. Here is the first trap: an account without a password cannot log in at the VNC console, and the password prompt from sudo can never be answered successfully. So set a password immediately afterwards:
passwd kernel
On RHEL-style systems, or inside a script, the equivalent reads:
useradd -m -s /bin/bash kernel
passwd kernel
Success check:
getent passwd kernel
ls -ld /home/kernel
passwd -S kernel
getent passwd kernel shows the home directory and the login shell; if it says /bin/sh or /usr/sbin/nologin, then usermod -s /bin/bash kernel corrects that. passwd -S kernel prints the state of the password in the second column: P for usable, L for locked, NP for none. After passwd kernel it has to read P.
The administrator group: sudo on Debian and Ubuntu, wheel on RHEL
A widespread misunderstanding: the group does not grant the privileges by itself. It only does so because /etc/sudoers holds a line that refers to it. On Debian and Ubuntu that line reads roughly %sudo ALL=(ALL:ALL) ALL, on RHEL-style systems %wheel ALL=(ALL) ALL. What is configured on your own machine is shown by:
grep -E '^[^#]*%' /etc/sudoers
On Ubuntu an additional line for the historical group admin shows up. That group no longer exists on current images, so the line has no effect. This is how you add the user:
usermod -aG sudo kernel
The -a is not optional. Without that switch, usermod -G replaces all supplementary groups with the list you supply, without a word of warning, and the damage often only surfaces weeks later. The switch works exclusively together with -G. An equivalent and less error-prone command is gpasswd -a kernel sudo.
Success check:
id -nG kernel
getent group sudo
sudo -l -U kernel
The last line is the most informative one, because it asks sudo itself. What you want is a block that ends in (ALL : ALL) ALL. If you get User kernel is not allowed to run sudo on srv01. instead, no rule applies.
Why the new group only takes effect at the next login
A process receives its group memberships at login and never again after that. That is why id -nG kernel run as root shows the group sudo, while the same output inside the user's own session does not contain it. Both are correct: one command reads the user database, the other reads the running session. The fix is a fresh login, not a reboot. newgrp sudo takes effect only in exactly the shell you call it in.
Editing sudoers safely: visudo and /etc/sudoers.d
Never open /etc/sudoers directly in an editor. One syntax error makes sudo unusable for every user, and once root has been switched off, the console is all that is left. visudo locks the file against concurrent changes and checks the syntax before saving. If it finds an error, it asks:
>>> /etc/sudoers: syntax error near line 22 <<<
What now?
Options are:
(e)dit sudoers file again
e(x)it without saving changes to sudoers file
(Q)uit and save changes to sudoers file (DANGER!)
The right answer is e; the capital Q saves the broken file. Which editor visudo launches is decided on Debian and Ubuntu by the alternatives system: permanently through update-alternatives --config editor, for a single run through EDITOR=nano visudo.
For your own rules, though, do not touch /etc/sudoers at all. At the end of that file, one line pulls in an entire directory, depending on the age of the system either as @includedir /etc/sudoers.d or as #includedir /etc/sudoers.d. The hash sign looks like a comment marker, but it is not one. You create this file with visudo as well:
visudo -f /etc/sudoers.d/10-kernel
The two rules that files in this directory fail on
The file name must not contain a dot and must not end in a tilde. sudo skips such files silently, so that backup copies cannot hand out privileges by accident. 10-kernel.conf is therefore never read, and not a single message says so. The correct name is 10-kernel.
The file has to be owned by root and must not be writable by group or others, the expected mode is 0440.
chown root:root /etc/sudoers.d/10-kernel
chmod 0440 /etc/sudoers.d/10-kernel
visudo -c
visudo -c checks every included file and prints one line per file:
/etc/sudoers: parsed OK
/etc/sudoers.d/10-kernel: parsed OK
That is also the best test for the first rule: if your file does not show up here, it is not being read, and a dot in the file name is almost always the cause. With wrong permissions, visudo reports /etc/sudoers.d/10-kernel: bad permissions, should be mode 0440 instead.
NOPASSWD: what it really costs
Sooner or later everyone comes across this line:
kernel ALL=(ALL) NOPASSWD: ALL
It is more dangerous than it looks. The password prompt is the last hurdle between "somebody has a shell as kernel" and "somebody is root". Anyone who reaches the account through a vulnerable web application, a copied private key or an unattended session is root with this line in place, without a single further step. With NOPASSWD: ALL, the security gain over logging in as root directly shrinks to one username that an attacker does not know.
NOPASSWD is justified where nobody can type: Ansible runs, backup scripts, deployment pipelines. Even there, keep it narrow, and not for the human at the terminal:
deploy ALL=(root) NOPASSWD: /usr/bin/systemctl restart nginx
Three pitfalls with rules like that:
- Absolute paths are mandatory. A program name without a path matches nothing.
- If no arguments are listed, all arguments are allowed.
deploy ALL=(root) NOPASSWD: /usr/bin/systemctlpermits any systemctl call. Only once you write the arguments down as well does the command line have to match exactly. If no argument at all should be allowed, append an empty argument pair, for example/usr/bin/id "". - Wildcards are rarely as narrow as they look.
/usr/bin/*allows every program in that directory and amounts to full root access in practice.
The key question with every restricted rule: can the permitted command start another program or open a shell? Editors, package managers, archive tools and interpreters can, and a rule that allows an editor through sudo allows everything in practice.
The better compromise is the caching period: by default sudo remembers a successful entry for 15 minutes, separately per terminal. You can adjust that under /etc/sudoers.d/:
Defaults:kernel timestamp_timeout=5
sudo -k discards the timestamp immediately, sudo -v refreshes it without running a command.
Getting the public key onto the new user
As long as password authentication over SSH is still enabled, the most convenient route from your workstation is ssh-copy-id kernel@203.0.113.10. If it has already been switched off, that fails with Permission denied (publickey). The way in then leads through the root session that is still open.
The obvious move there is cp -r /root/.ssh /home/kernel/.ssh, and it is wrong: afterwards the files belong to root, the SSH server rejects them, and the command drags along any private key root may have, which has no business sitting on a second account. Copy only the public keys instead, deliberately:
install -d -m 700 -o kernel -g kernel /home/kernel/.ssh
install -m 600 -o kernel -g kernel /root/.ssh/authorized_keys /home/kernel/.ssh/authorized_keys
install sets permissions and ownership in one go, so no forgotten chown is left behind. If /root/.ssh/authorized_keys does not exist, create the target file empty and enter the key with an editor:
install -m 600 -o kernel -g kernel /dev/null /home/kernel/.ssh/authorized_keys
Success check:
ls -ld /home/kernel /home/kernel/.ssh
ls -l /home/kernel/.ssh/authorized_keys
ssh-keygen -l -f /home/kernel/.ssh/authorized_keys
The last line prints the fingerprint of every key that is stored. Compare it with ssh-keygen -l -f ~/.ssh/id_ed25519.pub on your workstation. That way you know the right key has arrived before you even attempt the first login.
One detail that can cost hours: with StrictModes yes, the SSH server checks not only .ssh and authorized_keys but the home directory as well. If that is writable by group or others, it refuses the key login, and the client reports nothing more than Permission denied (publickey). The permissions your system hands out are set in /etc/adduser.conf under DIR_MODE. Everything about key login itself is in Securing SSH and setting up key login.
The test before you switch root off
Four checks, and only once all of them pass do you touch the SSH configuration. The old root session stays open.
First: a new SSH session as the new user, in a freshly opened window, not inside the existing connection.
ssh kernel@203.0.113.10
What you expect is a shell without a password prompt. If you are asked for a password, the key did not take; ssh -v shows which keys the client is offering in the first place. If the connection itself already stalls, Connecting to a server via SSH takes it from there.
Second: sudo in exactly that new session.
id
sudo -v
sudo id
id has to list the group sudo, and sudo id has to start with uid=0(root). A sudo -l -U kernel from the root session does not replace this test: it shows what sudo would permit, not whether the user's login works.
Third: the console. Log in through the VNC console in the customer panel as kernel with username and password, and run sudo -i there. This test is the most important of the four, because the console is the rescue route and it knows nothing but passwords.
Fourth: the state of the passwords.
passwd -S root
passwd -S kernel
At least one of the two accounts has to show a P in the second column. Two locked accounts plus a faulty SSH configuration add up to a system that can only be reached through a rescue system.
Switching root off, the right way
Three measures are often lumped together even though their consequences differ considerably.
| Measure | Effect | Consequence for the console |
|---|---|---|
PermitRootLogin prohibit-password | root gets in over SSH by key only, never with a password | none, root can still log in |
PermitRootLogin no | root cannot get in over SSH at all any more | none, root can still log in |
passwd -l root | root no longer has a usable password, key login and sudo -i remain untouched | only the sudo user can log in |
For most servers, prohibit-password is the right choice: root stays reachable by key as a last resort, while guessing passwords remains hopeless. The setting belongs in a file of its own under /etc/ssh/sshd_config.d/, and a syntax check comes before every restart of the service:
sshd -t && systemctl restart ssh
sshd -T | grep -i permitrootlogin
passwd -l root is the harsher variant and is only defensible once the third test above has actually been run. The command locks password authentication and nothing else: a stored SSH key keeps working, and so does sudo -i.
What is not advisable: taking the login shell away from root, for example with usermod -s /usr/sbin/nologin root. That blocks not only the login but also sudo -i and the emergency shell during boot.
Common errors and how to fix them
kernel is not in the sudoers file.: the user does not belong to any group that a rule exists for, or the session is older than the group change. Check id -nG kernel as root, then getent group sudo, then log in again. Older versions still append a sentence about the incident being reported.
sudo: 3 incorrect password attempts although you typed it correctly: the account has no password at all, typically because it was created with --disabled-password. passwd -S kernel then shows L or NP, and passwd kernel solves it. On top of that, sudo asks for the password of the calling user, not for root's.
sudo: no tty present and no askpass program specified: there is no terminal for sudo to ask on. Typical with ssh server 'sudo command' and in cron jobs. Over SSH, ssh -t helps; in a cron job the entry belongs in root's crontab.
sudo: /etc/sudoers.d/10-kernel is mode 0644, should be 0440: wrong permissions on the rule file. chmod 0440 fixes it; until then the rule has no effect.
/etc/sudoers.d/10-kernel: bad permissions, should be mode 0440: the same cause, reported by visudo -c. Run that command after every change.
The rule file does not appear in the output of visudo -c at all: the file name contains a dot or ends in a tilde. Rename 10-kernel.conf to 10-kernel.
usermod: group 'sudo' does not exist: you are working on a RHEL-style system. There the administrator group is called wheel, which getent group wheel confirms.
Permission denied (publickey) for the new user while root can still log in: almost always the permissions. /home/kernel/.ssh has to be 700, authorized_keys 600, both have to be owned by the user, and the home directory must not be writable by group or others. The cause is in the journal:
journalctl -t sshd -n 50 --no-pager
What you are looking for is a line that begins with Authentication refused: bad ownership or modes for directory and names the directory in question.
sudo: unable to resolve host srv01: Name or service not known: the hostname is missing from /etc/hosts. sudo still runs, but noticeably delayed. The matching entry is in the root server checklist.
And if the account is meant to disappear again: gpasswd -d kernel sudo takes away the privileges only, while deluser --remove-home kernel or userdel -r kernel removes it together with its home directory.
Distribution differences at a glance
| System | Group | What to watch for |
|---|---|---|
| Debian 13 (trixie) | sudo | sudo often not installed in minimal installations; adduser is a tool of its own and interactive |
| Debian 12 (bookworm) | sudo | same as Debian 13 |
| Ubuntu 24.04 LTS | sudo | sudo is present; with cloud-init there is often an account with sudo privileges already; a line for admin that has no effect |
| Ubuntu 22.04 LTS | sudo | same as Ubuntu 24.04 |
| AlmaLinux, Rocky, RHEL | wheel | the group sudo does not exist; adduser is just another name for useradd |
Short version
- Settle your way back: keep a second root session open, try the VNC console in the customer panel once, know the root password.
apt-get install -y sudoifcommand -v sudoreturns nothing.adduser --disabled-password --gecos "" kernel, thenpasswd kernel, so that the console stays usable.usermod -aG sudo kernel, on RHEL-style systemswheel. The-ais mandatory.- Transfer the public key with
install: directory 700, file 600, owned by the new user. - Your own rules only through
visudo -fin/etc/sudoers.d/, file name without a dot, mode 0440, thenvisudo -c. - Verify:
sudo -l -U kernel, a new SSH session,sudo id, a login at the console with a password. - Only after that touch
PermitRootLogin.
A user with sudo privileges takes away both the accidental total loss and the best known username. Against open ports the UFW firewall helps, and against attacks that saturate your connectivity only filtering in the network in front of it does, at KernelHost in the maincubes datacenter in Frankfurt am Main. On the server itself, your job stays the smallest one and at the same time the most effective: making sure that exactly one account holds exactly the privileges it needs.
Frequently asked questions
Do I even need a separate user if I work on the server on my own?
adduser or useradd, which one should I use?
Is the administrator group called sudo or wheel?
The user is in the group, but sudo still does not work.
Is NOPASSWD acceptable if I am the only one with access to the server?
My file under /etc/sudoers.d is being ignored. Why is that?
Does the new user need a password if I only log in with a key?
What do I do if I have locked myself out while editing sudoers?
2026 KernelHost GmbH. All rights reserved. This guide is protected by copyright. Republishing it on other websites, in whole, in part or in edited form, is not permitted without our written consent. Quoting with a source credit and a link is expressly welcome.

