M9K blog

Заметки ITшника обо всём

Путешествие в Сербию. Заметки.

Новосибирск

Ключ провернулся в замочной скважине с привычным звуком. Рюкзак, набитый всем необходимым и половиной ненужного, привычно вдавился в плечи. Ну что ж, дорога — веди.

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

Прохожу. Начинаю сомневаться в правильности решения. Помните начало «Субстанции»? Хочешь сделать что-то некрасивым — сними это максимально близко. Красивый лицевой портрет превратится в чёрт знает что, если кропнуть его до различимости пор. Эстетичное женское ню при чрезмерном приближении станет пособием проктолога-гинеколога-дерматовенеролога. Узкая платформа собирает чудной люд разной степени неприятности: какие-то сумрачные тётки, прыщавый подросток, залихватски рассказывающий про очередную танковую имбу, отвратительный мужик, решивший, что перрон — идеальное место, чтобы покурить.

Подползает электричка — старая, уставшая, с облупленной краской и выражением вечного «переплавьте меня». Поднимаюсь внутрь — мест, ожидаемо, нет. Встаю в тамбуре, толпа прижимает ко мне парня с гнилыми зубами. Закрываю глаза, запускаю музыку. Нужно потерпеть двадцать пять минут.

Станция назначения встречает гололёдом. Узкая скользкая лестница, которая должна бы вести прямо в травмпункт — сколько жертв на тебе было? Толчея на выходе, толчея в переходе. Пока поднимаюсь, заказываю машину. Ожидание пять минут, но тут вечные проблемы с разворотами. Захожу в магазин погреться, пока жду.

Машина подъезжает, сгружаю рюкзак в багажник. В салоне тепло. Класс заказанной машины, видимо, влияет на репертуар радио водителя — играет что-то из классики. Раздражённые электричкой нервы постепенно приходят в себя.

На дороге относительно мало машин. Выехали на новый мост, вылетели на трассу, ведущую в аэропорт. Двадцать минут — стекляшка Толмачёво встречает меня.

Захожу в здание. Внутри — привычный театр безопасности, но сегодня без драматургии: всё проходит быстро. Сегодня нам в международный терминал. Прохожу через «крытую» галерею — там привычно холодно. Интересно, что думают редкие иностранцы, которые всё-таки добираются до «столицы» Сибири, о таком архитектурно-утилитарном решении?

Мельком бросаю взгляд на табло. Так-с, у нас проблемы. Перед Стамбулом ещё три рейса, и это плохо: Толмачёво Международное, конечно, не худший российский терминал, но с пропускной способностью у него явные сложности. Вздыхаю, сгребаю металл в рюкзак, иду на второй этаж.

Хорошая новость — на паспортный контроль вывели всю смену. Плохая — на досмотре по-прежнему одна лента. Очередь движется нервными рывками. Ничего необычного: редколетающие пассажиры привычно пытаются что-то фотографировать, погранцы их привычно окрикивают. Передо мной женщина, явно опаздывающая на посадку, но её больше волнует шапка на ребёнке, чем прохождение формальностей. В путешествиях у каждого свой приоритет.

Протискиваюсь между пассажирами, не выгребшими заранее металл из карманов. Сорок минут — и я по ту сторону формальностей. До посадки ещё час — можно перевести дух. Захожу в местную едальню, привычно заказываю лимонад. Не то чтобы он был необходим, но тут есть столики и гарантированно рабочие розетки. Можно расслабиться и спокойно поработать за ноутбуком. Минут через десять понимаю, что желудок урчит. Ладно, попробуем местную высокую кухню.

Смотрю на табло. До посадки десять минут — пора собираться. Выхожу к гейту. Сегодня 737-й, полный. Народу — тьма. Объявляют посадку, но новые реалии стабильны: «Авиакомпания приносит свои извинения, задержка вызвана подготовкой самолёта». Ну, самолёт хотя бы на перроне — уже хорошо.

Десять минут — и посадка всё же начинается. Крайний гейт, выход через трапы, до которых нужно идти по полосе. Сегодня ветра нет, да и самолёт с двумя трапами, поэтому процесс проходит нормально.

Усаживаюсь. Место хоть и Extra Space, но не сказать, что слишком комфортное. В этом плане Airbus-ы интереснее. Плюс расстраивает время — 6:50. Мы же знаем, куда летим, и понимаем, что ближайшие семь с половиной часов это кресло станет пристанищем.

Театр продолжается. Дамы и господа, ваши ремни безопасности — мы готовы к взлёту. Самолёт отрывается от земли, оставляя за спиной привычное. Минут через двадцать выходим на эшелон. Что ж, это будет долгий полёт.

Почти семь часов одинаково некомфортны и днём, и ночью. Ночью хотя бы есть шанс уснуть, днём дрёмы в теплоте ласкающего солнца хватает минут на двадцать. Соседи тихие. Ладно, развлечёмся сериалами — благо заранее залил оба сезона Fallout.

Часы текут вязко. Иногда прохожусь по салону, иногда ем, иногда просто смотрю в иллюминатор на бесконечное небо. Всё это постепенно превращается в одно длинное «между».

Посматриваю в Organic Maps. Двести двадцать километров до цели, юг Чёрного моря. Бодрая скороговорка: наш самолёт приступил к снижению. Заходим в петлю над азиатской частью Стамбула, разворачиваемся над Кючюкчекмедже, выходим на глиссаду. Метры тают, полоса приближается. Мягкое касание — самолёт скользит по бетону. Здравствуйте, мы в Турции.

Стамбул

Впрочем, это не в первый раз, поэтому мы никуда не спешим. IST огромный, и рулёжка — ещё минут двадцать минимум. Так и есть: гейт, мягко говоря, далековат. Наконец выпускают. Как же приятно размять ноги! Идём на контроль. Там толчея, но к чести местных пограничников работают они быстро. Ещё десять минут — и размашистый штамп подтверждает наше право ступать по Малой Азии.

Привычный маршрут: багаж, таможня, зелёный коридор. Выхожу в зал прилётов. Чёрт, не помню, какой выход ближе к метро. Указатель ведёт к 13-му. Выхожу — обман, тысяча чертей. Идём к 11-му.

В метро транспортная карта оказывается ещё живой — на ней даже остались деньги. Маленькая победа путешественника.

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

Арнавуткёй встречает серым тяжёлым небом. После самолёта — отличная разминка: идти в горку. Через пять минут появляется перекрёсток с нужными заведениями. Сначала в магазин — мда, негусто. Большая часть ассортимента — снеки. Ладно, идём в кафе. Место явно для местных, но англоговорящий персонал есть. Короткие переговоры — заказываю пиде и чай. Официант предупреждает, что сейчас Рамадан, готовить будут дольше. Странно, но мы никуда не спешим.

Приносят суп и пиде. От размеров глаза лезут на лоб. Где-то на половине останавливаюсь, прошу счёт и упаковать остатки с собой. Это реально на двоих, а то и на троих. Завтрак на завтра готок.

Ещё несколько минут пешком — и отель. Формальности минимальны: бронирование есть, деньги списаны, добро пожаловать. Номер приятно удивляет — чисто, аккуратно, нормальное окно. За ним — огни и глиссада, самолёты заходят на посадку один за другим.

По внутренним часам уже глубокая ночь. Организм выключается без сопротивления. Душ, кровать — и Морфей забирает меня мгновенно, как будто всё это путешествие было лишь длинным прологом ко сну.

Меморис: цены на железо

В очередной раз совершив психологическую атаку на директорию «Разобрать (Мусор ( Новая папка (347)))» наткнулся на собственную калькуляцию на заказ на ПК от июля 2020 года.

В реалиях цен рф ничего под данный бюджет уже не существует из актуального в целом. Если брать более открытый рынок РК, то плюс-минус в бюджете остались корпуса да CPU.

Proxmox 7 + Debian 12|13 LXC Template

У Proxmox есть неплохая обратная совместимость с более свежими версиями LXC-контейнеров по сравнению с той версией Debian, на которой основан текущий релиз. В нашем случае используется Proxmox 7 (на базе Debian 11).

При попытке создать контейнер получаем ошибку вида:

TASK ERROR: unable to create CT 100 - unsupported debian version '1X'

Для обхода проблемы правим файл
/usr/share/perl5/PVE/LXC/Setup/Debian.pm в двух местах.

Обновляем карту версий:

my $version_map = { 'stretch/sid' => 9.1, 'buster/sid' => 10, 'bullseye/sid'=> 11, 'bookworm/sid'=> 12, 'trixie/sid' => 13, 'kali-rolling'=> 11, };

Расширяем допустимый диапазон версий:

if !($version >= 4 && $version <= 14);

После этого перезапускаем связанные демоны:

systemctl restart pvedaemon 
systemctl restart pveproxy

Готово, контейнер успешно создаётся.

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

Меморис: цены на память.

Тёмная сторона силы GM в 2026 — это неадекватный ценник на компьютерное железо. Зашёл посмотреть свою историю заказов в ритейлере, который есть и в РК, и рф, и бодро подивился на цифру.

За полгода ценник сделал бодрый x6. Наверно, мало какой товар на планете показывал такие сумрачные цифры роста. Помнится, даже в середине десятых, когда был первый криптобум, и все массово ломанулись скупать видеокарты, рост был и то не такой впечатляющий.

«Источник» бед резюмирует:

Рост цен на ОЗУ сейчас (2025—2026): ~200—300%+ за год — можно сказать, почти трёхкратный взрыв.
Рост цен на видеокарты в криптобум (2016—2018): обычно ~30—70% над MSRP (из-за дефицита, спекуляций, спроса майнеров).

Sasha Komovich — Расскажи, Снегурочка

Генеративные модели плотно вошли в нашу жизнь. Если пару лет назад первые версии Midjourney лично мной воспринимались как игрушка, то теперь сложно представить быт, работу и досуг без условного GPT4ALL или Invoke. То же самое касается и искусства — пусть абсолютная часть генерируемого контента мусор (как, впрочем, и с вещами, которые делали кожаные мешки до явления GM), но стоит наконец признать: это не более чем ещё один инструмент креатива. Трендовый бриллиант начала 2026-го — доказательство тому.

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

 7   1 мес   AI   Sasha Komovich   youtube   музыка

Синематики Star Wars

Справедливое в комментариях:
Remember, as long as the only evidence of a game’s existence is a CGI trailer, it doesn’t exist.
Но все равно красиво.

Нейрогенеративная Нара

Будучи в Японии, сделал великолепный снимок одного из храмов в Наре.

Попробовал поиграться со стилизациями изображения под разные локации. Получилось минимум забавно...а местами грустно.

STALKER2 PS5 Trailer

Время летит быстро — без малого года прошёл с момента релиза. Зашёл на второе прохождение, игра по состоянию на патч 1.6 прекрасна.

 20   4 мес   stalker 2   trailer   youtube

Конак и Қонақ үй

Листал карту Белграда и наткнулся на достопримечательность «Конак кнеза Милоша» (усадьба князя Милоша). Слово и смысл показалось подозрительно знакомыми с казахским «Қонақ үй» (гостиница). Короткий GPT-гуглинг подтвердил мои подозрения:

Серб. konak ‘усадьба, резиденция, постоялый двор’ — это заимствование из османо-тур. konak ‘большой дом, резиденция; постоялый двор’. Турецкое konak связано с глаголом kon-(mak) ‘останавливаться на ночлег, садиться (о птице), размещаться’.

Казахск. қонақ үй — буквально ‘дом для гостей’: қонақ ‘гость’ + үй ‘дом’. Слово қонақ — исконно тюркское, от того же корня қон- ‘садиться, останавливаться на ночлег’.

Итог: сербское konak — турцизм эпохи Османской империи; казахское қонақ — родное тюркское. Оба восходят к одному пра-тюркскому корню *kon- ‘останавливаться/переночевать’.

Windows перемещение файлов в директории по совпадению части имени

В указанной директории ищем файлы с «_45» или «_16», перемещаем во внутреннюю создаваемую директорию.

$dir = "C:\work\pics"
$target = Join-Path $dir 'substrateInstagram'
New-Item -ItemType Directory -Path $target -Force | Out-Null
Get-ChildItem -Path $dir -Filter *.jpg -File |
  Where-Object { $_.BaseName -match '(_45|_16)' } |
  Move-Item -Destination $target

Linux Passwordless oneliner

TARGET=user@host; PORT=22; [[ -r ~/.ssh/id_ed25519.pub ]] || ssh-keygen -t ed25519 -N "" -f ~/.ssh/id_ed25519; ssh -p "$PORT" "$TARGET" 'umask 077; mkdir -p ~/.ssh && cat > ~/.ssh/authorized_keys' < ~/.ssh/id_ed25519.pub && ssh -p "$PORT" "$TARGET" 'echo ">>> Root доступ подтверждён"'

CouchDB, Debian, AstraLinux, Docker и все-все-все

Возникла необходимость запустить Couchdb в контейнере, где базовая ось (и базовые же пакеты) должны быть очень-очень свежими, в противной случай контейнер не проходит встроенную проверку на безопасность.
Стандартный официальный образ собран на базе Debian 12.

FROM debian:bookworm-slim

Простая замена базового образа на

FROM debian:trixie-slim

приводит к тому, что контейнер не собирается по зависимостям.
Смотрим официальную репу в части зависимостей и видим прекрасное — libmozjs-78-0 (>= 78.15.0). Пробуем ставить свежую версию, которая есть в репах — не помогает, пакет couchdb принципиально требует libmozjs-78-0.

Ок, скрещиваем ежа и ужа.

У debian есть механизм apt-pinning. Это механизм, позволяющий задать приоритеты для версий пакетов из разных источников (репозиториев, release-веток, PPA), чтобы фиксировать версию, запрещать обновление или предпочитать конкретный источник.

Коротко приоритеты делятся на:

  • < 0 — никогда не устанавливать.
  • 1..99 — ставить только при явном указании версии.
  • 100 — приоритет уже установленной версии.
  • 500 — дефолт для неприоритетных источников.
  • 990 — приоритет для целевого релиза (-t), либо если явно указан release.
  • >1000 — разрешает понижение версии (downgrade) к закреплённой.

Добавляет в наш Dockerfile:

RUN echo "deb http://deb.debian.org/debian bookworm main" > /etc/apt/sources.list.d/bookworm.list && \
    echo "Package: *\nPin: release n=bookworm\nPin-Priority: 500" > /etc/apt/preferences.d/bookworm && \
    echo "Package: *\nPin: release n=trixie\nPin-Priority: 600" > /etc/apt/preferences.d/trixie && \
    echo "deb [signed-by=/usr/share/keyrings/couchdb-archive-keyring.gpg] https://apache.jfrog.io/artifactory/couchdb-deb/ bookworm main" \
            > /etc/apt/sources.list.d/couchdb.list && \
    apt-get update

Основная часть пакетов ставится из свежей репы, часть, которых в ней нет — из старых.

Curl over ssh-tls-tunnel

Есть ресурс resource.name, на который нужно ходить curl-ом с засылкой данных через JSON. Специфика ресурса такова, что он принимает соединения через TLS 1.3.
Есть сервер A server.name, на котором нет выхода на нужный ресурс, но есть Nginx, и есть ssh-доступ до сервера B
Есть сервер B, на котором есть выход на нужный ресурс, но сам сервер очень старый, и TLS на нём не проходит по требования resource.name.

printf '' | openssl s_client -connect 127.0.0.1:8443 -servername resource.name -tls1_3 -brief

Костылим:
На сервере A поднимаем туннель на внутренний порт:

ssh -fN -o ExitOnForwardFailure=yes -o ServerAliveInterval=60 -o ServerAliveCountMax=3 -L 8443:resource.name:443 user@serverB

На Nginx рисуем конфиг:

server {
        listen 9090;
        server_name         server.name;

        access_log  /site/logs/nginx/port_9090.log  main;
        error_log   /site/logs/nginx/port_9090.error.log;

location / {
        proxy_pass https://127.0.0.1:8443;

        proxy_set_header Host resource.name;
        proxy_ssl_server_name on;
        proxy_ssl_name resource.name;
        proxy_ssl_protocols TLSv1.3;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto https;
        proxy_connect_timeout 10s;
        proxy_read_timeout 60s;
        proxy_ssl_verify off;
}
}

Кидаемся тестовым запросом:

curl -v -X POST 'http://server.name:9090/resource' -H 'Content-Type: application/json' --data '{"login":"$LOGIN","password":"$PASSWORD"}'

Unzip без unzip

Есть сервер без выхода в сеть с древней ОС и мёртвыми репами. Нужно распаковать zip-архив — но утилиты нет.
Решаем вопрос python-ом:

python - <<'EOF'
import zipfile, os
archive = 'archive.zip'
target_dir = 'archive.zip'

if not os.path.exists(target_dir):
    os.makedirs(target_dir)

with zipfile.ZipFile(archive, 'r') as z:
    for name in z.namelist():
        z.extract(name, target_dir)
EOF

Multistage Docker — как пересобирать без кэша не весь Dockefile

Возникла необходимость пересобрать отдельный stage-контейнер из Dockerfile. Первый собранный контейнер — это контейнер сборки OpenSSL, который выполняется очень, очень долго. Для того, чтоб сэкономить время, во вторую часть добавляем:

# Stage 1: OpenSSL-сборка (пусть останется закешированной)
FROM debian:bookworm AS openssl-build
# ... 
# Stage 2: основная
FROM debian:bookworm-slim
# Аргумент, чтобы инвалидировать кэш
ARG CACHE_BREAKER=default
# Используем его в ENV, чтобы Docker счёл слой новым
ENV CACHE_BREAKER=${CACHE_BREAKER}
Ранее Ctrl + ↓