Об администрировании сервера

Сегодня, в эпоху облачных провайдеров и SaaS, управлять сервером самостоятельно — крайне нишевое занятие. Для этого нужно очень хорошо разбираться в Linux и его многочисленных системных компонентах, которые, к тому же, постоянно обновляются и меняются, из-за чего знания и опыт быстро устаревают. Я много лет пользуюсь Linux, но и то не знаю всех тонкостей, постоянно учусь. Сама система принципиально несложная и понятная, но в ней постоянно появляется что-то новое, какие-то дополнительные слои абстракции. Linux многолик, его можно использовать в самых разных контекстах — отсюда и сложность. Ну и, конечно, знать систему на уровне десктопа — это одно, а админить по SSH — слегка другое.

Не хочу никого пугать надуманными страшилками: в сервере нет ничего мистического, чаще всего это обычный Ubuntu, где все точно такое же, как и в десктопных версиях (только нет собственно десктопа). Умеешь пользоваться терминалом, можешь научиться и сервером управлять. Но сервер — это более специфическая среда, тут у вас не просто рут и «хомяк». Надо серьезно заботиться о правах доступа и постоянно думать о том, не под угрозой ли безопасность. На десктопе угрозы чаще всего условные — ваш комп никто извне не станет ломать, никому вы не нужны. А вот сервер попытаются запросто. Любой мало-мальски посещаемый сайт постоянно осаждают боты в попытках взломать или заспамить. Поэтому головным мозгом думать надо постоянно, взвешивая каждый свой шаг. chmod тут не для галочки.

Хорошая новость — Linux стабилен. Ядро падает крайне редко, я за всю жизнь ни разу не видел, чтобы система падала из-за проблемы именно в ядре. На десктопе все крахи из-за неправильно настроенных приложений. Чаще всего падает графическая подсистема (раньше это были «иксы» — X11, сейчас еще и Wayland), либо чудят драйверы. На сервере графики нет, и внешние устройства не подключаются, так что единожды запущенная система будет работать, пока какая-нибудь авария не случится. А сломать Linux нечаянно в процессе каких-то настроек — это надо иметь особую степень криворукости. Зато вот ломающиеся серверные приложения — это суровые будни админа! Софт под Linux встречается самого разного качества — Open Source же. Все всегда запускается на свой страх и риск. Можно очень легко попортить любые данные, если они не защищены от записи. Поэтому бэкапы надо делать регулярно. Никогда нельзя запускать никакие команды или скрипты, если не понимаешь, что они делают. На сервере все проблемы от бездумных действий. Если на десктопе обычно работаешь под непривилегированным пользователем, а sudo для административных действий — это исключение, то на сервере все наоборот: root — норма, работа под другими пользователями — исключение. Но постоянно приходится помнить: настраиваешь что-то из-под рута — готовься к ошибкам типа «permission denied». Создал из-под рута какой-нибудь файлик, забыл выставить нужные права — все, будешь полдня искать причину полома.

Скажу честно: я не большой фанат Docker, я предпочитаю все ставить самостоятельно прямо в систему. Докером пользуюсь только в тех случаях, когда надо что-то совсем уж экстраординарное и навороченное, в чем лень разбираться. Например, у меня в контейнере запущен Nextcloud. Да, лень — это вообще-то не самая уважительная причина в данном контексте, но и я не профессиональный админ, а просто юзер, которого жизнь заставила админить. Поэтому я и не адепт всей этой контейнерной религии — да и вообще не сторонник каких-либо определенных DevOps-практик. Мне кажется, чем проще, тем лучше. Если Docker упрощает жизнь — то хорошо, берем на вооружение, а если с ним все становится сложнее, то ну его.

Проще всего поставить классический комплект из веб-сервера, PHP и MySQL (или MariaDB). Справится абсолютный новичок. Даже сертификаты сегодня уже не обязательно самому ставить — Caddy делает это за вас. Нужно только немного понимать, как работает стек TCP/IP (впрочем, если вам только обычные сайты писать, то и полноценный сервер не нужен, достаточно shared-хостинга).

Наверное, у всех, кто что-то разрабатывал под веб, был период, когда хочется написать свою серверную программу. Так вот, это ровно до того момента, когда вы действительно сможете запустить ее на реальном сервере. Только тогда начинаешь понимать, что к чему в плане безопасности. Энтузиазм велосипедить отпадает, вырабатывается склонность ставить чужое, но надежное. Взять тот же WordPress — да, система неидеальная. Да, то и дело что-то там отваливается после обновлений. Да, плагины быстро устаревают. Но WP все равно лучше, чем самописный движок. Свое писать стоит, только если совсем уж нет никакого выхода, если у вас задача какая-то узкоспециализированная. Например, сложный CI/CD или игровой сервер.

Админство — совсем не творческое занятие, а жутко рутинное. Это постоянная правка всевозможных конфигов и написание скриптов, установка пакетов, управление Systemd, копание в логах, мониторинг портов и, конечно, лихорадочные поиски документации в Интернете. Запустили сервис, потестили, увидели проблему, остановили, фиксим. Потом еще раз, и еще, и еще… Главное, что я понял — лучше вообще не вкатываться во все это без особой насущной необходимости. Обычному человеку должно хватать бесплатных сервисов, предоставляемых корпорациями. Вот когда уже не хватает, и «хочется странного» — другое дело.

Например, мой путь в администрирование начался, когда понадобился личный/семейный VPN. Думал этим и ограничиться, но затем понеслось. Сервер — это мир больших соблазнов. Поставил одно, тут же хочется попробовать другое, ведь почти всем популярным сервисам есть self-hosted аналоги: можно поднять личные аналоги GitHub, Google Workspace, Spotify и бог знает чего еще. Настраивать и дорабатывать напильником все это можно бесконечно — есть маньяки, которые именно этим большую часть свободного времени и занимаются) Для меня идеал — один раз настроил и забыл, но, к сожалению, так получается далеко не всегда.

C3: неужели наконец-то нормальный C-подобный язык?

Современная замена C — это то, чего очень не хватает всем, кто пишет что-то для десктопа с нуля, не полагаясь на популярнные платформы типа веба, Java/.Net, скриптовых языков и т.д. До настоящего времени реального аналога C, можно сказать, не было вовсе (исключением является BetterC-режим D, но это все-таки не отдельный язык, а подмножество, и он не для «зашедших с улицы», а совсем наоборот — для самых опытных программистов на D). Go и Rust не предлагать! 🤣

И вот, захожу я, как обычно, в ньюсгруппу d.D и вижу ссылку на C3: https://c3-lang.org. «Продать» мне что-то новомодное сложно, но язык зацепил! Я тестировал еще не все фичи, но вот что понравилось практически сразу:

  • Компилятор довольно легко установить. Вначале, правда, выкачивается майкрософтовский SDK, но после этого компилятор становится самостоятельным и Студию не требует;
  • Не нужна отдельная система сборки, компилятор сам выполняет ее функции;
  • Простая и вменяемая система типов, полностью совместимая с C без костылей;
  • Векторы, матрицы и кватернионы в стандартной библиотеке — бесценно! Сразу уйма работы отпадает при написании игрового движка;
  • Вообще, в целом, читаемая и красивая стандартная либа. Открываешь любой модуль, и все понятно;
  • Управление памятью, чем-то похожее на то, что я делаю в dlib (аллокаторы, универсальный new). Сборщика мусора нет;
  • Красивая обработка ошибок со встроенным Optional и проверкой на null на уровне синтаксиса. Optional — это просто модификатор типа: если его использовать, то компилятор тупо не дает прочитать такую переменную без предварительного null-чекинга. Можно его делать самостоятельно, а можно просто использовать оператор «!!», тогда компилятор вставит проверку сам. Все выглядит очень просто и читаемо.

Конечно, многого пока не хватает — например, нет менеджера пакетов. Биндинги к некоторым популярным библиотекам есть тут, но я пока не разобрался, как они линкуются, документации по этой теме нет. Нативных библиотек, ясное дело, тоже выбор пока совсем минимальный. Еще один жирный минус — не поддерживается компиляция в bare metal, а без этого язык нельзя назвать системным, и стопроцентной заменой C он считаться, строго говоря, не может.

Обновления

Dagon 0.23.1

Небольшое обновление Dagon 0.23. Добавлена поддержка переключения отдельных рендер-таргетов в PassTerrain — то есть, для материалов ландшафта работают свойства outputColor, outputNormal и др. Движок теперь использует dlib 1.3.2. Добавлены новые уроки — 9, 13 и 15.

К следующему релизу готовлю поддержку Assimp, о которой уже писал, а также перенос расширения dagon:ftfont в ядро движка, что позволит реализовать различные встроенные UI-компоненты.

BindbC-Assimp

Биндинг к Assimp 5 размещен на GitHub и доступен в качестве DUB-пакета. К сожалению, название bindbc-assimp занято заброшенным и несуществующим ныне проектом, поэтому пришлось зарегать как bindbc-assimp5.

Оптимизация блога

Я настроил объектный кэш на основе Redis, а также добавил HTML-кэш и заголовок Cache-Control, что заметно ускорило загрузку страниц блога. Было исправлено множество мелких проблем верстки. Все архивные игры теперь размещены на одном сервере с блогом.

Тема, которую я использую, теперь также доступна на GitHub. Это форк WPEX Blogger 1.2 от WPExplorer, в котором я внес исправления для совместимости с PHP 8, исправил поиск в мобильном меню, добавил новые переводы на русский, а также внес патч, исправляющий совместимость с плагином Code Syntax Block.

Поддержка Assimp

Библиотека Assimp — относительно тяжеловесное, но самое функциональное решение для загрузки 3D-моделей. У меня наконец-то дошли руки добавить поддержку Assimp 5+ в Dagon как расширение dagon:assimp, благодаря чему можно будет использовать в движке модели форматов FBX, Collada, 3DS и многих других. Пока загружаются только меши, но в планах добавить поддержку материалов, узлов и анимации.

Перед загрузкой модели можно задать кастомные флаги постпроцессора:

AssimpAsset aModel;

override void beforeLoad()
{
    aModel = this.addAssimpAsset("assets/cacodemon.fbx");
    aModel.loaderOption =
        aiPostProcessSteps.Triangulate | aiPostProcessSteps.FlipUVs;
}

После этого можно использовать меши из массива aModel.meshes для рендеринга:

auto e = addEntity();
e.drawable = aModel.meshes[0];