На сервер встала свежая Ubuntu Server 26.04 LTS. Свежий релиз — это не только новые версии пакетов, но и новые умолчания, о которых ещё нигде не написано. Ниже десять мест, где система повела себя не так, как я ожидал по прошлым версиям. А в конце — приборная доска на физическом экране ноутбука, которая в первой версии съедала 17% ядра, а после переписывания — 1%.
Это четвёртая часть цикла «Домашняя инфраструктура».
Десять граблей первой недели
1. Свой .link-файл для сети не применяется
Я положил /etc/systemd/network/10-wol.link, чтобы включить Wake on LAN. Он молча игнорировался: netplan генерирует свой 10-netplan-<интерфейс>.link, а udev применяет первый подходящий файл по алфавиту. Всё сетевое задаётся в самом netplan — для WoL это wakeonlan: true.
2. Пароли в SSH остались включены
Установщик кладёт /etc/ssh/sshd_config.d/50-cloud-init.conf с PasswordAuthentication yes. А в sshd побеждает первое встреченное значение, не последнее. Файл с ужесточением, названный «как обычно» с большим номером, проиграет. Свой файл называем так, чтобы он читался первым: 00-hardening.conf. Проверка — не по файлам, а по итоговому конфигу: sshd -T | grep passwordauthentication.
3. Время не синхронизируется
Из домашней сети оказались недоступны все десять NTP-источников по умолчанию. Заменил на ru.pool.ntp.org и time.cloudflare.com. И имейте в виду: в 26.04 нет systemd-timesyncd, временем заведует chrony — chronyc sources, а не timedatectl timesync-status.
4. Часы убежали на три часа
BIOS хранил местное время, Linux считал его UTC. У всех источников было смещение +10801s. Лечение: chronyc makestep, затем hwclock --systohc, чтобы записать правильное время обратно в BIOS.
5. В журнале нет sshd и не работает last
С OpenSSH 9.8 сессии пишутся под именем sshd-session, и старые фильтры по sshd их пропускают. wtmp в системе нет, поэтому last пуст — историю входов искать в журнале.
6. printf ломает выравнивание кириллицы
printf '%-10s' в bash считает байты, а не символы, и русские подписи разъезжаются: в UTF-8 буква занимает два байта. Пришлось написать свою функцию дополнения пробелами и выставить LC_ALL=C.UTF-8.
7. Docker обходит UFW
Не новость, но в свежей системе об этом легко забыть: опубликованный порт контейнера открыт, что бы ни говорил ufw status. Базы наружу не публикуем, ограничения — в цепочке DOCKER-USER.
8. В консоли вопросики вместо русских букв
Шрифт консоли по умолчанию — Lat15. Лечение:
# /etc/default/console-setup
CHARMAP="UTF-8"
CODESET="Uni2"
FONTFACE="TerminusBold"
FONTSIZE="8x16"
setupcon --force --save
9. Посмотреть физический экран из SSH
Иногда надо увидеть, что сейчас показано на мониторе сервера, не подходя к нему. Содержимое первой консоли лежит в /dev/vcsu1 — в UTF-32, по четыре байта на символ (/dev/vcs1 искажает кириллицу):
COLS=$(stty -F /dev/tty1 size | cut -d' ' -f2); LINES=$(stty -F /dev/tty1 size | cut -d' ' -f1)
sudo dd if=/dev/vcsu1 bs=$((COLS*4)) count=$LINES 2>/dev/null | iconv -f UCS-4LE -t UTF-8 | fold -w $COLS
10. Часть coreutils переписана на Rust
В 26.04 часть стандартных утилит — реализации uutils. В обычной работе разницы нет, но редкие флаги иногда ведут себя иначе. Если скрипт, проверенный годами, вдруг падает на sort или date, — вспомните об этом.
Три настройки, которые стоит сделать сразу
- журнал:
Storage=persistentиSystemMaxUse=500M. Без лимита он имеет право вырасти до 10% раздела — на нашем диске это около 11 ГБ; - Docker: в
daemon.jsonротация журналов контейнеров (max-size 10m,max-file 3) иlive-restore— перезапуск демона не роняет контейнеры; - подкачка:
vm.swappiness60 → 10 иvfs_cache_pressure=50. На машине с 3,2 ГБ памяти с момента загрузки в подкачку успело уехать 22,8 ГБ — система охотно выгружала и тут же загружала обратно.
Приборная доска на экране ноутбука
Раз у сервера есть экран, пусть показывает, что происходит. На первой консоли запущен скрипт: сверху закреплённая шапка с процессором, температурой, памятью, подкачкой, диском, батареей («от сети» или «от батареи») и шкалами входящего и исходящего трафика; снизу бегущий журнал — события ядра, Docker и обращения к сайтам со статусом кэша и пометкой, бот это или человек.
Шапка не прокручивается за счёт области прокрутки терминала: ESC[top;bottom r ограничивает прокрутку нижней частью экрана, а шапку перерисовываем, сохраняя и восстанавливая курсор (ESC 7 / ESC 8).
17% ядра на «посмотреть»
Первая версия была написана как обычный скрипт: $( ) на каждое значение, вызовы docker info, free и numfmt каждые три секунды, посимвольные циклы для шкал. Она ела около 17% ядра и 124 МБ памяти — на сервере с четырьмя потоками это много.
Переписал на встроенные средства bash: /proc и /sys читаются через read без внешних программ, время — из $EPOCHSECONDS и printf '%(…)T', функции пишут результат в глобальные переменные вместо подстановки $( ), которая каждый раз порождает процесс. Стало 1% ядра и 21 МБ.
# сколько процессорного времени съела служба — точнее, чем top на глаз
systemctl show dashboard.service -p CPUUsageNSec
Журнал прокси для доски я перевёл в JSON, оставив восемь нужных полей. Полная строка весила около 1120 байт, урезанная — 451, примерно 6,8 МБ в сутки. И сразу пригодилось: доска тут же показала страницу каталога, которая без кэша собиралась 7,37 секунды, а из кэша отдавалась за 7 мс.
Перевели журнал в JSON — перепроверьте всё, что его читает. У меня это сломало fail2ban на 13 дней, о чём была первая часть цикла.
Мелочи
- после правки скрипта службу надо перезапустить — иначе крутится старая копия, загруженная в память;
- скорость сети на первом такте не показывать: делить не на что, и доска рисует «1,5 ГБ/с»;
- метки в журнале — латиницей (HIT, MISS, BYP), потому что
printfсчитает байты; - скрипт игнорирует Ctrl+C (
trap '' INT), чтобы его не убили случайно с клавиатуры. Обратная сторона: копию, запущенную в SSH, так тоже не остановить — закрывать вкладку или запускать черезtimeout. Аpkillбез-t pts/Nубьёт и экземпляр на экране.
Ставите свежий LTS на сервер?
Напишите, что за машина и что на ней будет, — пройдусь по умолчаниям, которые стоит поменять в первый же день.
// загружаю комментарии…