Первые 30 минут на новом сервере: пользователь, SSH-ключи, ufw
Свежий VPS с Ubuntu 24.04 обычно выдают с паролем root и портом SSH, открытым для всего интернета. Подбор паролей к SSH идёт круглые сутки, и новый адрес попадает под него быстро. Если сомневаетесь, через пару часов после создания машины выполните sudo journalctl -u ssh | grep -c "Invalid user" и посмотрите на число. Ниже порядок на полчаса. В конце на сервер можно войти только по ключу и только под своим пользователем, а снаружи открыто лишь то, что вы разрешили. После каждого шага идёт проверка: ошибка в настройках SSH запирает сервер вместе с вами.
Минуты 0–5: первый вход и обновления
Из панели провайдера понадобятся IP-адрес, пароль root (или ключ, если вы добавили его при создании машины) и веб-консоль. Консоль работает как монитор с клавиатурой, подключённые прямо к серверу, и от настроек SSH не зависит. Если дальше что-то пойдёт не так, войти можно будет через неё.
При первом подключении клиент SSH покажет отпечаток ключа сервера и спросит, доверять ли ему. Чтобы не отвечать yes вслепую, откройте веб-консоль и выведите отпечаток на самом сервере:
ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub
Строка SHA256:… должна совпасть с той, что показал клиент. Теперь входите, убедитесь, что система та, и обновите её:
ssh root@203.0.113.10
grep VERSION= /etc/os-release
apt update && apt full-upgrade -y
ls /var/run/reboot-required && reboot
Адрес 203.0.113.10 условный, здесь и дальше подставляйте свой. Файл reboot-required появляется, когда обновление требует перезагрузки, чаще всего после нового ядра. Тогда последняя строка перезагрузит машину, и через минуту нужно войти снова. Часть провайдеров вместо root заводит пользователя ubuntu с правами sudo. В этом случае команды выполняйте через sudo, а своего пользователя можно не создавать.
Минуты 5–15: свой пользователь и ключ
Под root любая опечатка выполняется с полными правами, а само имя root перебирает каждый бот. Поэтому работать лучше под обычным пользователем с sudo. Имя любое, в примерах это deploy:
adduser deploy
usermod -aG sudo deploy
adduser попросит пароль, а дальше имя, телефон и прочие поля, их можно пропустить клавишей Enter. Пароль нужен для sudo. Входить с ним по SSH после следующего шага уже не получится.
Ключ создают на своём компьютере, не на сервере. Тип ed25519 даёт короткий ключ, который понимают все актуальные версии OpenSSH. В Windows 10 и 11 клиент OpenSSH встроен, команда та же, только в PowerShell:
ssh-keygen -t ed25519 -C "laptop"
Программа предложит путь (Enter оставит ~/.ssh/id_ed25519) и парольную фразу. Фраза шифрует закрытый ключ на диске, и если ноутбук украдут, воспользоваться ключом без неё не выйдет. Вводить её при каждом входе не обязательно, это берёт на себя ssh-agent.
Открытую часть ключа (файл .pub) нужно дописать в ~/.ssh/authorized_keys пользователя на сервере. В Linux для этого есть готовая команда:
ssh-copy-id deploy@203.0.113.10
В Windows её нет, ту же работу делает одна строка в PowerShell:
type $env:USERPROFILE\.ssh\id_ed25519.pub | ssh deploy@203.0.113.10 "mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"
Обе команды входят на сервер по паролю deploy, поэтому их запускают, пока вход по паролю ещё работает. Бывает и наоборот: провайдер при создании машины уже положил ваш ключ к root, а пароль для SSH отключён. Тогда скопируйте ключ новому пользователю прямо на сервере, из сессии root:
mkdir -p /home/deploy/.ssh
cp /root/.ssh/authorized_keys /home/deploy/.ssh/
chown -R deploy:deploy /home/deploy/.ssh
chmod 700 /home/deploy/.ssh
Проверка шага: из нового окна выполните ssh deploy@203.0.113.10. Сервер не должен спрашивать пароль (парольную фразу ключа может спросить клиент, это другое), а sudo whoami после ввода пароля deploy отвечает root.
Минуты 15–22: SSH только по ключу и без root
В Ubuntu 24.04 на этом шаге есть ловушка. Главный файл /etc/ssh/sshd_config в самом начале подключает всё из каталога /etc/ssh/sshd_config.d/, а sshd для каждого параметра берёт первое найденное значение. На облачных образах cloud-init кладёт в этот каталог файл 50-cloud-init.conf со строкой PasswordAuthentication yes. Если исправить только sshd_config, вход по паролю продолжит работать.
Свои настройки поэтому кладут в отдельный файл, имя которого по алфавиту идёт раньше файла cloud-init:
sudo nano /etc/ssh/sshd_config.d/10-hardening.conf
Содержимое:
PermitRootLogin no
PasswordAuthentication no
KbdInteractiveAuthentication no
PubkeyAuthentication yes
AllowUsers deploy
AllowUsers пускает по SSH только перечисленных пользователей. Когда заведёте второго, допишите его в эту строку через пробел, иначе он не войдёт. Дальше проверьте синтаксис и итоговые значения, потом перезапустите службу:
sudo sshd -t
sudo sshd -T | grep -Ei '^(permitrootlogin|passwordauthentication|kbdinteractiveauthentication) '
sudo systemctl restart ssh
Если ошибок нет, sshd -t ничего не выводит. sshd -T печатает настройки, которые получились после чтения всех файлов, и во всех трёх строках должно стоять no. Служба в Ubuntu называется ssh, а не sshd.
Окно, в котором вы всё это делали, пока не закрывайте. Перезапуск службы не обрывает открытые сессии, и через это окно можно вернуть всё назад. Во втором терминале войдите как deploy. Вошли, значит, первое окно можно закрыть.
Минуты 22–27: файрвол ufw
В Ubuntu 24.04 ufw обычно уже установлен, но выключен: sudo ufw status покажет inactive. Если пакета нет, поставьте его командой sudo apt install ufw. Сначала задают правила, включают файрвол последним:
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw limit OpenSSH
sudo ufw allow 80,443/tcp
sudo ufw enable
sudo ufw status verbose
OpenSSH в третьей строке означает профиль приложения, который положил пакет openssh-server, он открывает 22/tcp. Вместо allow стоит limit: если с одного адреса за 30 секунд пришло шесть подключений или больше, ufw отклоняет следующие. Вам при обычной работе это не мешает, а перебор замедляет. Строка с портами 80 и 443 нужна, только если на сервере будет сайт. Правила для IPv6 ufw добавляет сам, по умолчанию в /etc/default/ufw стоит IPV6=yes.
Команда ufw enable предупредит, что может оборвать SSH-соединения, и попросит подтверждения. Правило для SSH к этому моменту уже есть, так что отвечайте y.
С Docker есть оговорка. Порты, которые контейнер публикует через -p или раздел ports в docker compose, Docker открывает своими правилами iptables, и ufw их не фильтрует. Базу данных или админку в контейнере публикуйте только на локальный адрес, например 127.0.0.1:5432:5432, а наружу выводите через обратный прокси.
У многих провайдеров в панели есть и сетевой файрвол. Он стоит перед машиной и ufw не заменяет. Если порт закрыт в панели, правило ufw его не откроет: когда сайт не отвечает, а в ufw всё разрешено, загляните туда.
Минуты 27–30: обновления, время и снимок
В Ubuntu Server пакет unattended-upgrades установлен и включён сразу: каждый день он ставит обновления безопасности. Убедиться в этом можно по файлу настроек:
cat /etc/apt/apt.conf.d/20auto-upgrades
В обеих строках должно стоять "1". Если файла нет, выполните sudo apt install unattended-upgrades, а затем sudo dpkg-reconfigure -plow unattended-upgrades.
Сам перезагружать сервер после обновления ядра пакет по умолчанию не будет. Когда перезагрузка нужна, появляется уже знакомый файл /var/run/reboot-required, а при входе по SSH об этом напомнит строка *** System restart required ***. Время для неё выбирайте сами, когда на сервере мало работы.
Команда timedatectl должна показывать System clock synchronized: yes. Часовой пояс влияет на время в журналах и в заданиях cron, поменять его можно так: sudo timedatectl set-timezone Europe/Moscow.
Напоследок сделайте в панели провайдера снапшот. К этой чистой точке можно откатиться, если следующая установка что-то сломает. Чем снапшот отличается от настоящей резервной копии, написано в статье о выборе VPS.
Проверка за две минуты
Все проверки, кроме последних трёх, запускайте со своего компьютера. Если результат другой, вернитесь к нужному шагу.
| Что проверяем | Команда | Ожидаемый результат |
|---|---|---|
| Вход по ключу | ssh deploy@203.0.113.10 | Входит без пароля сервера |
| Root закрыт | ssh root@203.0.113.10 | Permission denied (publickey) |
| Пароль выключен | ssh -o PubkeyAuthentication=no deploy@203.0.113.10 | Permission denied (publickey) |
| Итоговые настройки SSH | sudo sshd -T | grep -i passwordauthentication | passwordauthentication no |
| Файрвол | sudo ufw status verbose | Status: active, deny (incoming), OpenSSH с LIMIT |
| Кто слушает порты | sudo ss -tlnp | Только службы, которые вы ставили, и локальный DNS на 127.0.0.53 |
Частые вопросы
Нужно ли менять порт SSH с 22 на другой?
Защиты это не добавляет: сканер найдёт SSH на любом порту. Перенос лишь убирает из журнала большую часть автоматического перебора. Если всё же переносите, сначала откройте новый порт в ufw. В Ubuntu 24.04 SSH запускается через сокет systemd, поэтому после правки Port в sshd_config выполните sudo systemctl daemon-reload и sudo systemctl restart ssh.socket, иначе сервер продолжит слушать 22.
Что делать, если SSH больше не пускает?
Откройте веб-консоль в панели провайдера и войдите как deploy с паролем, который задали в adduser: консоль от настроек SSH не зависит. Поправьте или удалите /etc/ssh/sshd_config.d/10-hardening.conf и перезапустите службу командой sudo systemctl restart ssh. Если доступ закрыл ufw, выполните sudo ufw disable. Когда консоли нет, остаётся режим восстановления из панели.
Нужен ли fail2ban, если вход по паролю выключен?
Для SSH он уже не обязателен: подбор паролей к входу по ключу ничего не даст, а limit в ufw отсекает частые подключения. fail2ban полезен, если на сервере есть другие службы с паролями, например веб-панель или почта. Он читает их журналы и закрывает вход адресам после нескольких ошибок подряд.
Подойдёт ли этот порядок для Debian 12?
В целом да, с тремя отличиями. В минимальной Debian может не оказаться sudo и ufw, их ставят через apt install sudo ufw. SSH там работает обычной службой, без сокета systemd. Файла от cloud-init в sshd_config.d может не быть, но итоговые значения в любом случае покажет sudo sshd -T.