Как создать пользователя с правами sudo и перестать работать под root

Опубликовано 14 мин. чтения

adduser или useradd, группы sudo и wheel, безопасная правка sudoers через visudo и проверка, которая подтверждает, что вы не закрыли себе доступ, прежде чем отключать root.

Сразу после развёртывания сервера вы работаете под root, а root делает всё и никогда не переспрашивает. Любая опечатка тут же бьёт по всей системе, и при этом root остаётся единственным именем пользователя, которое заведомо известно каждому атакующему. В этом руководстве разобран весь путь целиком: создать пользователя, включить его в нужную группу, дополнить конфигурацию sudoers, перенести открытый ключ и только в самом конце отключить root. Самая важная часть стоит незадолго до финала: доказательство того, что вы не закрыли доступ самому себе.

Опорные системы: Debian 13 (trixie), Debian 12 (bookworm), Ubuntu 24.04 LTS и Ubuntu 22.04 LTS. Там, где системы семейства RHEL, такие как AlmaLinux и Rocky Linux, ведут себя иначе, это отмечено отдельно. Команды написаны из расчёта работы под root; если вы работаете под обычным пользователем, добавляйте перед каждой командой sudo. Краткая версия есть в чек-листе для нового root-сервера, а здесь идёт подробный разбор.

Прежде чем что-то менять: путь назад

Доступа здесь могут лишить два изменения: конфигурация sudoers и, в самом конце, разрешение для root входить по SSH. Сломанный файл sudoers отбирает у вас права, а слишком рано отключённый вход root — запасной путь. Поэтому три вещи стоит выяснить заранее.

Второй сеанс. Откройте второе окно терминала с активным SSH-соединением под root и не закрывайте его, пока всё не проверено. Уже установленный сеанс переживает и перезапуск службы SSH, и сломанный файл sudoers.

Путь в обход SSH. Для KVM root-серверов и выделенных серверов KernelHost откройте VNC-консоль в личном кабинете. Она подключена к уровню виртуализации, а на выделенном сервере непосредственно к самой машине, то есть не зависит ни от SSH, ни от файрвола, ни от файла sudoers. Войдите через неё один раз заранее: аварийный путь, который впервые пробуют уже в самой аварии, аварийным путём не является.

Пароль, который вы знаете. Консоль не знает SSH-ключей: там вы входите по имени пользователя и паролю либо не входите вовсе. Именно здесь чаще всего и теряют доступ.

Простое правило: аварийный путь — это консоль, а консоль знает только пароли. Прежде чем отключать вход по паролю, хотя бы у одной учётной записи должен быть пароль, который вы знаете.

Осмотр на месте: а sudo вообще установлен?

В серверных образах Ubuntu sudo есть, в минимальных образах Debian его часто нет. Исходное положение проясняют три строки:

command -v sudo || echo "sudo не установлен"
getent group sudo
awk -F: '$3 >= 1000 && $3 < 65534 {print $1, $3, $7}' /etc/passwd

Вторая строка показывает группу вместе с её участниками, третья — все обычные учётные записи с идентификатором и командной оболочкой. В образах с cloud-init учётная запись с правами sudo нередко уже давно существует. Если sudo нет, доставьте его:

apt-get update
apt-get install -y sudo
sudo -V | head -n 1

adduser или useradd: два инструмента, два результата

Тот, кто пользуется useradd, а ожидает поведения adduser, получает учётную запись без домашнего каталога и с оболочкой, на которую он совершенно не рассчитывал.

Свойствоadduseruseradd
ДоступностьDebian и Ubuntuвезде, в том числе в системах семейства RHEL
Режим работыинтерактивный, спрашивает пароль и поля с именемделает только то, что указано в ключах
Домашний каталогсоздаётся и наполняется из /etc/skelтолько с -m
Командная оболочкаиз /etc/adduser.confиз /etc/default/useradd, часто /bin/sh
Парользапрашивается, кроме случая с --disabled-passwordне задаётся никогда
В системах семейства RHELпросто другое имя для useraddсобственно рабочий инструмент

В Debian и Ubuntu правильным выбором будет adduser:

adduser --disabled-password --gecos "" kernel

--gecos "" пропускает вопросы об имени и телефонных номерах, --disabled-password создаёт учётную запись без пароля. Здесь подстерегает первая ловушка: учётная запись без пароля не сможет войти через VNC-консоль, а на запрос пароля от sudo никогда не получится ответить успешно. Поэтому сразу же задайте пароль:

passwd kernel

В системах семейства RHEL или в скрипте равнозначный вариант выглядит так:

useradd -m -s /bin/bash kernel
passwd kernel

Проверка результата:

getent passwd kernel
ls -ld /home/kernel
passwd -S kernel

getent passwd kernel показывает домашний каталог и командную оболочку; если там стоит /bin/sh или /usr/sbin/nologin, это исправит usermod -s /bin/bash kernel. passwd -S kernel выводит во втором столбце состояние пароля: P означает пригодный к использованию, L заблокированный, NP отсутствие пароля. После passwd kernel там должно стоять P.

Группа администраторов: sudo в Debian и Ubuntu, wheel в RHEL

Распространённое заблуждение: сама по себе группа никаких прав не выдаёт. Права появляются лишь потому, что в /etc/sudoers есть строка, которая на эту группу ссылается. В Debian и Ubuntu она выглядит примерно как %sudo ALL=(ALL:ALL) ALL, в системах семейства RHEL как %wheel ALL=(ALL) ALL. Что прописано именно у вас, покажет:

grep -E '^[^#]*%' /etc/sudoers

В Ubuntu дополнительно появляется строка для исторической группы admin. В актуальных образах этой группы уже нет, поэтому строка ни на что не влияет. Пользователя добавляют в группу так:

usermod -aG sudo kernel

Ключ -a пропускать нельзя. Без него usermod -G молча заменяет все дополнительные группы на указанный список, и ущерб нередко обнаруживается лишь недели спустя. Действует этот ключ исключительно вместе с -G. Равнозначный и менее опасный вариант: gpasswd -a kernel sudo.

Проверка результата:

id -nG kernel
getent group sudo
sudo -l -U kernel

Последняя строка самая показательная: она спрашивает сам sudo. Ожидается блок, который заканчивается на (ALL : ALL) ALL. Если вместо этого приходит User kernel is not allowed to run sudo on srv01., значит, не срабатывает ни одно правило.

Почему новая группа начинает действовать только при следующем входе

Членство в группах процесс получает при входе в систему и после этого больше не обновляет. Поэтому id -nG kernel, запущенный от root, показывает группу sudo, тогда как тот же самый вывод внутри сеанса самого пользователя её не содержит. Верно и то и другое: одна команда читает базу пользователей, вторая — текущий сеанс. Решение: новый вход в систему, а не перезагрузка. newgrp sudo действует ровно в той оболочке, в которой вы его вызвали.

Как безопасно править sudoers: visudo и /etc/sudoers.d

Никогда не открывайте /etc/sudoers напрямую в редакторе. Синтаксическая ошибка делает sudo непригодным сразу для всех пользователей, а если root к тому моменту уже отключён, останется только консоль. visudo блокирует файл от одновременного редактирования и проверяет синтаксис перед сохранением. Найдя ошибку, он задаёт вопрос:

>>> /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!)

Правильный ответ: e; большая Q сохраняет ошибочный файл. Какой редактор запустит visudo, в Debian и Ubuntu определяет система альтернатив: постоянно через update-alternatives --config editor, разово через EDITOR=nano visudo.

Впрочем, ради собственных правил /etc/sudoers трогать вообще не нужно. В конце файла стоит строка, которая подключает целый каталог: в зависимости от возраста системы это @includedir /etc/sudoers.d или #includedir /etc/sudoers.d. Решётка выглядит как знак комментария, но комментарием не является. Свой файл вы тоже создаёте через visudo:

visudo -f /etc/sudoers.d/10-kernel

Два правила, о которые спотыкаются файлы в этом каталоге

Имя файла не должно содержать точку и не должно заканчиваться тильдой. Такие файлы sudo молча пропускает, чтобы резервные копии случайно не раздали права. Поэтому 10-kernel.conf не будет прочитан никогда, причём без единого сообщения. Правильный вариант: 10-kernel.

Файл должен принадлежать root и не должен быть доступен на запись группе и остальным, ожидается режим 0440.

chown root:root /etc/sudoers.d/10-kernel
chmod 0440 /etc/sudoers.d/10-kernel
visudo -c

visudo -c проверяет все подключённые файлы и выводит по одной строке на каждый:

/etc/sudoers: parsed OK
/etc/sudoers.d/10-kernel: parsed OK

Это заодно и лучшая проверка первого правила: если вашего файла в списке нет, значит, он не читается, и тогда почти всегда виновата точка в имени файла. При неверных правах visudo вместо этого сообщает /etc/sudoers.d/10-kernel: bad permissions, should be mode 0440.

NOPASSWD: во что это обходится на самом деле

Рано или поздно на эту строку натыкается каждый:

kernel ALL=(ALL) NOPASSWD: ALL

Она опаснее, чем кажется. Запрос пароля — это последний рубеж между «у кого-то есть оболочка от имени kernel» и «кто-то стал root». Тот, кто доберётся до учётной записи через уязвимое веб-приложение, скопированный закрытый ключ или оставленный без присмотра сеанс, с этой строкой становится root без единого дополнительного шага. С NOPASSWD: ALL весь выигрыш в безопасности по сравнению с прямым входом под root сжимается до одного имени пользователя, которого атакующий не знает.

Оправдан NOPASSWD там, где вводить пароль просто некому: запуски Ansible, скрипты резервного копирования, пайплайны развёртывания. Но тогда узко ограниченный и точно не для человека за терминалом:

deploy ALL=(root) NOPASSWD: /usr/bin/systemctl restart nginx

Три подводных камня в таких правилах:

  • Абсолютные пути обязательны. Имя программы без пути не совпадает ни с чем.
  • Если аргументы не перечислены, разрешены любые аргументы. deploy ALL=(root) NOPASSWD: /usr/bin/systemctl допускает любой вызов systemctl. Только если вы выпишете аргументы явно, командная строка обязана выглядеть в точности так. А если не должно быть разрешено ни одного аргумента, добавьте пустую пару кавычек, например /usr/bin/id "".
  • Подстановочные знаки редко бывают такими узкими, какими кажутся. /usr/bin/* разрешает любую программу в этом каталоге и на практике равносилен полному root-доступу.

Главный вопрос к любому ограниченному правилу: может ли разрешённая команда запустить другую программу или открыть оболочку? Редакторы, менеджеры пакетов, архиваторы и интерпретаторы это умеют, и правило, которое разрешает запуск редактора через sudo, на практике разрешает всё.

Более удачный компромисс: время запоминания. По умолчанию sudo помнит успешный ввод пароля 15 минут, причём отдельно для каждого терминала. Настроить это можно в /etc/sudoers.d/:

Defaults:kernel timestamp_timeout=5

sudo -k сбрасывает эту отметку сразу же, sudo -v обновляет её, не выполняя никакой команды.

Как перенести открытый ключ новому пользователю

Пока вход по паролю через SSH ещё активен, удобнее всего сделать это с рабочей машины командой ssh-copy-id kernel@203.0.113.10. Если он уже отключён, попытка сорвётся с сообщением Permission denied (publickey). Тогда путь идёт через ещё открытый сеанс root.

Первое, что напрашивается в этот момент, это cp -r /root/.ssh /home/kernel/.ssh, и это ошибка: файлы после такой команды принадлежат root, SSH-сервер их отвергает, а сама команда заодно тащит с собой закрытый ключ root, если он там есть, а ему во второй учётной записи делать нечего. Вместо этого перенесите прицельно только открытые ключи:

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 выставляет права и владельца за один заход, так что забытого chown после себя не оставляет. Если файла /root/.ssh/authorized_keys нет, создайте целевой файл пустым и впишите ключ редактором:

install -m 600 -o kernel -g kernel /dev/null /home/kernel/.ssh/authorized_keys

Проверка результата:

ls -ld /home/kernel /home/kernel/.ssh
ls -l /home/kernel/.ssh/authorized_keys
ssh-keygen -l -f /home/kernel/.ssh/authorized_keys

Последняя строка выводит отпечаток для каждого сохранённого ключа. Сравните его с выводом ssh-keygen -l -f ~/.ssh/id_ed25519.pub на вашей рабочей машине. Так вы ещё до первой попытки входа будете знать, что доехал именно нужный ключ.

Деталь, которая способна стоить нескольких часов: при StrictModes yes SSH-сервер проверяет не только .ssh и authorized_keys, но и сам домашний каталог. Если он доступен на запись группе или остальным, сервер отклоняет вход по ключу, а клиент сообщает лишь Permission denied (publickey). Какие права раздаёт ваша система, записано в /etc/adduser.conf в параметре DIR_MODE. Всё о самом входе по ключу собрано в статье Защита SSH и настройка входа по ключу.

Проверка перед тем, как отключать root

Четыре проверки, и только когда все они пройдены, вы берётесь за конфигурацию SSH. Старый сеанс root при этом остаётся открытым.

Первое: новый SSH-сеанс от имени нового пользователя, в только что открытом окне, а не в уже установленном соединении.

ssh kernel@203.0.113.10

Ожидается оболочка без запроса пароля. Если пароль всё-таки спрашивают, ключ не сработал; ssh -v покажет, какие ключи клиент вообще предлагает. Если сбоит уже само установление соединения, дальше поможет Подключение к серверу по SSH.

Второе: sudo именно в этом новом сеансе.

id
sudo -v
sudo id

id должен перечислить группу sudo, а вывод sudo id должен начинаться с uid=0(root). Команда sudo -l -U kernel из сеанса root эту проверку не заменяет: она показывает, что sudo разрешил бы, но не то, работает ли вход самого пользователя.

Третье: консоль. Войдите через VNC-консоль в личном кабинете как kernel, по имени пользователя и паролю, и выполните там sudo -i. Эта проверка самая важная из четырёх, потому что консоль и есть аварийный путь, а знает она только пароли.

Четвёртое: состояние паролей.

passwd -S root
passwd -S kernel

Хотя бы у одной из двух учётных записей во втором столбце должно стоять P. Две заблокированные учётные записи плюс ошибочная конфигурация SSH дают систему, до которой можно добраться уже только через аварийный режим восстановления.

Как правильно отключить root

Три меры часто валят в одну кучу, хотя последствия у них совершенно разные.

МераЧто делаетПоследствия для консоли
PermitRootLogin prohibit-passwordroot заходит по SSH только с ключом, паролем уже никогданикаких, root по-прежнему может войти
PermitRootLogin noroot по SSH не заходит вообщеникаких, root по-прежнему может войти
passwd -l rootу root больше нет пригодного пароля, вход по ключу и sudo -i остаются нетронутымивойти сможет только пользователь с sudo

Для большинства серверов правильный выбор: prohibit-password. root остаётся доступен по ключу как аварийная возможность, а перебор паролей при этом всё равно бесперспективен. Эту настройку следует положить в отдельный файл в /etc/ssh/sshd_config.d/, и перед каждым перезапуском службы идёт проверка синтаксиса:

sshd -t && systemctl restart ssh
sshd -T | grep -i permitrootlogin

passwd -l root — вариант жёстче, и он оправдан только после того, как третья проверка из списка выше действительно пройдена. Команда блокирует исключительно вход по паролю: сохранённый SSH-ключ продолжает работать, sudo -i тоже.

Чего делать точно не стоит: отбирать у root командную оболочку, например через usermod -s /usr/sbin/nologin root. Это блокирует не только вход, но и sudo -i, и аварийную оболочку при загрузке системы.

Частые ошибки и их решения

kernel is not in the sudoers file.: пользователь не входит ни в одну группу, для которой существует правило, либо сеанс старше, чем изменение состава групп. Проверьте id -nG kernel от root, затем getent group sudo, после чего войдите заново. Старые версии добавляют к этому ещё фразу о том, что об инциденте будет доложено.

sudo: 3 incorrect password attempts, хотя набирали вы правильно: у учётной записи вообще нет пароля, как правило потому, что она создана с --disabled-password. passwd -S kernel покажет тогда L или NP, а passwd kernel это исправит. К тому же sudo спрашивает пароль вызывающего пользователя, а не пароль root.

sudo: no tty present and no askpass program specified: нет терминала, на котором sudo мог бы задать вопрос. Типично для ssh server 'sudo команда' и для заданий cron. При SSH помогает ssh -t, а в задании cron запись должна лежать в crontab пользователя root.

sudo: /etc/sudoers.d/10-kernel is mode 0644, should be 0440: неверные права на файле правил. chmod 0440 это исправляет; до тех пор правило не действует.

/etc/sudoers.d/10-kernel: bad permissions, should be mode 0440: та же причина, только сообщение приходит от visudo -c. Выполняйте эту команду после каждого изменения.

Файл правил вообще не появляется в выводе visudo -c: значит, его имя содержит точку или заканчивается тильдой. Переименуйте 10-kernel.conf в 10-kernel.

usermod: group 'sudo' does not exist: вы работаете в системе семейства RHEL. Там группа администраторов называется wheel, что подтверждает getent group wheel.

Permission denied (publickey) у нового пользователя, тогда как root по-прежнему заходит: почти всегда дело в правах. У /home/kernel/.ssh должен быть режим 700, у authorized_keys 600, оба должны принадлежать пользователю, а домашний каталог не должен быть доступен на запись группе и остальным. Причина видна в журнале:

journalctl -t sshd -n 50 --no-pager

Искать нужно строку, которая начинается с Authentication refused: bad ownership or modes for directory и называет проблемный каталог.

sudo: unable to resolve host srv01: Name or service not known: имени хоста нет в /etc/hosts. sudo при этом всё равно отрабатывает, но с заметной задержкой. Нужная запись приведена в чек-листе по root-серверу.

А если учётную запись нужно снова убрать: gpasswd -d kernel sudo отбирает только права, а deluser --remove-home kernel либо userdel -r kernel удаляет её вместе с домашним каталогом.

Различия между дистрибутивами одним взглядом

СистемаГруппаОсобенность
Debian 13 (trixie)sudoв минимальных установках sudo часто не установлен; adduser самостоятельный и интерактивный
Debian 12 (bookworm)sudoкак в Debian 13
Ubuntu 24.04 LTSsudosudo уже установлен; при cloud-init часто есть готовая учётная запись с правами sudo; ни на что не влияющая строка для admin
Ubuntu 22.04 LTSsudoкак в Ubuntu 24.04
AlmaLinux, Rocky, RHELwheelгруппы sudo не существует; adduser просто другое имя для useradd

Краткая версия

  1. Продумайте путь назад: держите открытым второй сеанс root, один раз попробуйте VNC-консоль в личном кабинете, знайте пароль root.
  2. apt-get install -y sudo, если command -v sudo ничего не возвращает.
  3. adduser --disabled-password --gecos "" kernel, затем passwd kernel, чтобы консоль осталась пригодной для входа.
  4. usermod -aG sudo kernel, в системах семейства RHEL wheel. Ключ -a обязателен.
  5. Перенесите открытый ключ командой install: каталог 700, файл 600, владелец: новый пользователь.
  6. Собственные правила только через visudo -f в /etc/sudoers.d/, имя файла без точки, режим 0440, после этого visudo -c.
  7. Проверьте: sudo -l -U kernel, новый SSH-сеанс, sudo id, вход в консоль по паролю.
  8. И только после этого беритесь за PermitRootLogin.

Пользователь с правами sudo избавляет вас от случайного разрушения всей системы и от самого известного имени пользователя. От открытых портов помогает файрвол UFW, а от атак, которые забивают канал, помогает только фильтрация в сети перед сервером, у KernelHost это дата-центр maincubes во Франкфурте-на-Майне. На самом сервере за вами остаётся самая маленькая и одновременно самая действенная задача: чтобы ровно одна учётная запись имела ровно те права, которые ей нужны.

Частые вопросы

Нужен ли отдельный пользователь, если я работаю на сервере один?
Да, и обе причины никак не связаны с количеством людей. Под root любая опечатка тут же бьёт по всей системе, тогда как обычная учётная запись упрётся в нехватку прав раньше, чем успеет что-то испортить. К тому же root остаётся единственным именем пользователя, которое уже известно любой автоматической попытке входа. Отключив его для SSH, вы обесцениваете значительную часть таких попыток, и следить за этим отдельно не придётся.
adduser или useradd: что выбрать?
В Debian и Ubuntu adduser. Он создаёт домашний каталог, наполняет его из /etc/skel, выдаёт пригодную командную оболочку и запрашивает остальные данные. useradd лежит уровнем ниже и делает исключительно то, что указано в ключах: без -m домашнего каталога не будет, без -s возьмётся значение по умолчанию из /etc/default/useradd, а там часто стоит /bin/sh. В системах семейства RHEL, таких как AlmaLinux и Rocky Linux, этого выбора у вас нет: там adduser просто другое имя для useradd.
Как называется группа администраторов: sudo или wheel?
В Debian 13, Debian 12, Ubuntu 24.04 и Ubuntu 22.04 она называется sudo, в системах семейства RHEL это wheel. Но решает не имя, а строка в /etc/sudoers, которая на эту группу ссылается. Какая она в вашей системе, покажет grep -E '^[^#]*%' /etc/sudoers. Если usermod прерывается сообщением «group 'sudo' does not exist», вы работаете в системе второго типа.
Пользователь в группе, но sudo всё равно не работает.
Почти всегда причина в том, что членство в группах процесс получает при входе в систему и после этого оно уже не меняется. Уже запущенный сеанс о команде usermod ничего не знает. Выйдите и войдите заново. Проверить можно обе стороны: id -nG kernel от root читает базу пользователей, а id внутри сеанса самого пользователя показывает состояние этого сеанса. Если группу показывают оба, а sudo по-прежнему отказывает, посмотрите через sudo -l -U kernel, срабатывает ли вообще хоть одно правило.
Можно ли использовать NOPASSWD, если доступ к серверу есть только у меня?
Для автоматизации да, но узко ограниченным списком отдельных команд с абсолютным путём. Для учётной записи, под которой вы работаете каждый день, так делать не стоит. Запрос пароля — это последний рубеж между оболочкой под вашим именем пользователя и полными правами root. Тот, кто доберётся до учётной записи через уязвимое приложение, скопированный закрытый ключ или оставленный без присмотра сеанс, с NOPASSWD: ALL становится root без единого дополнительного шага. Если вам мешает только частота запросов, лучше поменяйте время запоминания через timestamp_timeout, а не отключайте запрос совсем.
Мой файл в /etc/sudoers.d игнорируется. В чём причина?
Дело в одном из двух правил. Во-первых, sudo молча пропускает любой файл, имя которого содержит точку или заканчивается тильдой: 10-kernel.conf не будет прочитан никогда, а 10-kernel будет. Во-вторых, файл должен принадлежать root и иметь режим 0440, иначе sudo сообщит «is mode 0644, should be 0440» и правило не сработает. Оба случая показывает visudo -c. При неверных правах он сообщает «bad permissions, should be mode 0440», а если вашего файла в списке проверенных вообще нет, причина в имени файла.
Нужен ли новому пользователю пароль, если я вхожу только по ключу?
Да. VNC-консоль в личном кабинете — это ваш аварийный путь, когда SSH перестаёт отвечать, а консоль не знает ключей, только имя пользователя и пароль. Учётная запись, созданная с --disabled-password, войти там не сможет и вдобавок никогда не ответит на запрос пароля от sudo, что приводит к «sudo: 3 incorrect password attempts», хотя набирали вы правильно. Поэтому задайте пароль командой passwd kernel, прежде чем отключать root. После этого passwd -S kernel должен показывать во втором столбце P.
Что делать, если я закрыл себе доступ при правке sudoers?
Пока ваш сеанс root ещё открыт, поправьте файл прямо в нём: именно поэтому он и остаётся открытым на всё время перестройки. Если сеанс закрыт, а sudo сломан, путь идёт через VNC-консоль в личном кабинете, при условии что вы можете войти там как root или под учётной записью с действующим паролем. Остальное — профилактика: собственные правила создавайте только через visudo -f в файле внутри /etc/sudoers.d/, после этого выполняйте visudo -c, а на вопрос visudo никогда не выбирайте большую Q, которая сохраняет ошибочный файл.

sudo управление пользователями Linux Debian Ubuntu visudo безопасность сервера SSH