🏠: it

Демонстрации Yamaha W7 и автоматическое деление аудиофайла на части

Обнаружил сайт demodb.org, где можно послушать демки со старых синтезаторов, меня интересовала Yamaha W7.

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

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

Теперь нужно было порезать получившуюся запись на части. Конечно, мне сразу же захотелось это автоматизировать. Очевидно, разделителями являются периоды тишины, и после недолгого поиска я обнаружил, что в великом и могучем ffmpeg обнаружением тишины в аудиосигнале занимается фильтр silencedetect.

Экспериментальным способом выяснилось, что подходящим порогом срабатывания является -50 дБ, и silencedetect выдаёт такое:

[silencedetect @ 0000025b206a7740] silence_start: 0
[silencedetect @ 0000025b206a7740] silence_end: 4.11882 | silence_duration: 4.11882
[silencedetect @ 0000025b206a7740] silence_start: 213.267
[silencedetect @ 0000025b206a7740] silence_end: 218.22 | silence_duration: 4.95304
[silencedetect @ 0000025b206a7740] silence_start: 342.852
[silencedetect @ 0000025b206a7740] silence_end: 354.239 | silence_duration: 11.387
[silencedetect @ 0000025b206a7740] silence_start: 530.661
[silencedetect @ 0000025b206a7740] silence_end: 540.122 | silence_duration: 9.4607
[silencedetect @ 0000025b206a7740] silence_start: 670.007
[silencedetect @ 0000025b206a7740] silence_end: 680.196 | silence_duration: 10.1893
[silencedetect @ 0000025b206a7740] silence_start: 853.138
[silencedetect @ 0000025b206a7740] silence_end: 867.126 | silence_duration: 13.9884

Полезный сигнал начинается с silence_end, а заканчивается на silence_start, поэтому нужно выбросить первый silence_start и последний silence_end, итого 5 треков. Перед началом трека делается отступ в 0,25 сек, а в конце добавляется 1 сек, чтобы треки в списке не игрались attacca и между ними была какая-то пауза. В ffmpeg указывается не конечное время, а длительность нужного куска, поэтому нужно для этого из конечного времени вычесть начальное.

Иногда, например, у альбомов на Youtube, звук начинается сразу и первая метка silence_end оказывается уже на втором треке, поэтому нужно предусмотреть такие ситуации. Здесь я предположил, что если метка позже 30-й секунды, то вставлять в начало списка silence_end ноль и не удалять первый silence_start, т. к. нужно знать, где первая дорожка кончается. Соответственно, команда ffmpeg будет без указания стартовой позиции.

# Исходный файл
$file = 'D:\Музыка\Yamaha W7 demos.wav'
# Отступ до и после полезного сигнала (чтобы треки не начинались сразу один за другим)
$preSec = 0.25
$postSec = 1
# Формат файлов на выходе
$outputExt = ".mp3"

$file = get-item -literalpath $file
$log = (& ffmpeg -i $file.FullName -af silencedetect=n=-50dB:d=1 -f null - 2>&1) -match '^\[silencedetect'

$starts,$ends = $log.where({$_ -match 'silence_end'}, 'Split')
[regex]$replOut =  '.*?: (\d+\.\d+).*'
$starts = $starts -replace $replOut,'$1' |select -SkipLast 1
$ends = $ends -replace $replOut,'$1'
# Если в начале тишины нет (первое начало позднее 30-й секунды)
if ([double]$starts[0] -gt 30) {
    $starts = ,"0" + $starts
}
else {
    $ends = $ends |select -Skip 1
}

$c = 0
$starts |% {
    if ($_ -eq 0) {
        & ffmpeg -y -hide_banner `
        -t ([double]$ends[$c] + $postSec) `
        -i $file.FullName `
        ($file.DirectoryName + "\" + ($c+1).tostring("00") + " $($file.BaseName)" + $outputExt)
    }
    else {
        & ffmpeg -y -hide_banner `
        -ss ([double]$starts[$c] - $preSec) `
        -t ([double]$ends[$c] - [double]$starts[$c] + $postSec) `
        -i $file.FullName `
        ($file.DirectoryName + "\" + ($c+1).tostring("00") + " $($file.BaseName)" + $outputExt)
    }
    $c++
}

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

Надо сказать, что тех демонстраций, которые я выкладывал, когда рассказывал о своей неудачной карьере аранжировщика, я нигде не нашёл; видимо, они были на какой-то дополнительно приобретаемой дискете и их никто не записал. Зато нашёл другие, которые я тоже вспомнил, и они великолепны, а Isn’t it hip и Halftime просто, я бы сказал, исключительны. Структура композиций, динамика, гармонизация, подголоски, выбор тембров и их обработка — всё на высшем уровне.

Yamaha - Isn’t It Hip (Yamaha W5/W7 demo, 1994)

Последний бастион VMware

Сегодня на работе я выключил последнюю оставшуюся ноду после миграции всех виртуальных машин в кластер Hyper-V.

Последнее действие перед выключением Последнее действие перед выключением

Сервер был ProLiant DL380 G6, его уже давно пора было выводить из эксплуатации, но дело в том, что на нём крутилась пара серверов, «защищённых» USB-токеном. Несколько недель назад, наконец, купили железку, которая пробрасывает USB-устройства по сети — это местная аппаратная адаптация недорогого зарубежного решения VirtualHere.

Железка представляет собой keepalived-кластер из двух Banana Pi с веб-интерфейсом на ajenti и 32 портами USB, заключённых в едином корпусе:

# dmesg
[    0.000000] Booting Linux on physical CPU 0x0
[    0.000000] Linux version 5.15.93 (oe-user@oe-host) (arm-poky-linux-gnueabi-gcc (GCC) 9.3.0, GNU ld (GNU Binutils) 2.34.0.20200220) #1 SMP Thu Feb 9 10:26:48 UTC 2023
[    0.000000] CPU: ARMv7 Processor [410fc074] revision 4 (ARMv7), cr=10c5387d
[    0.000000] CPU: div instructions available: patching division code
[    0.000000] CPU: PIPT / VIPT nonaliasing data cache, VIPT aliasing instruction cache
[    0.000000] OF: fdt: Machine model: LeMaker Banana Pi
# lsb_release -a
LSB Version:    n/a
Distributor ID: poky
Description:    Poky (Yocto Project Reference Distro) 3.1.17
Release:        3.1.17
Codename:       dunfell

Документация написана не то чтобы очень и в настройке есть некоторые особенности, но техподдержка отвечает и в целом девайс работает хорошо.

Веб-интерфейс

На компьютерах, которым нужно подключение USB, ставится клиент, который устанавливает свои драйверы и может работать как служба. На очень старых системах, например, Windows 2003, драйверы нужно ставить самостоятельно, вытащив их из клиента с помощью командной строки. Потом, подмонтировав ключ, надо сделать так, чтобы служба сервера, зависящая от ключа (например, 1C:Enterprise 8.3 Server Agent), стартовала позже службы rhclient (USB Hub Over Network USB Sharing) — для этого нужно её перевести в режим автоматического отложенного запуска. В старых системах, где функции отложенного запуска нет, можно перевести службу сервера в ручной режим запуска и настроить планировщик задач, чтобы после загрузки ОС выполнялся скрипт наподобие

ping 127.0.0.1 -n 30
net start hwserver

Вот как выглядят устройства USB на виртуальной машине Hyper-V, где крутится 1С (напоминаю, что Hyper-V не пробрасывает USB с хоста на виртуалки, и правильно делает):

А вот так ключи выглядят с клиента:

Доступ к самим ключам и к их администрированию через клиент может быть ограничен несколькими способами, я делал по IP-адресам и подсетям.

Собственно, возвращаясь к тому, с чего я начал — после переноса токенов на железку оставалось только мигрировать все виртуалки на Hyper-V и выключить ноду VMware, что я и проделал. Теперь, наконец, зоопарка систем виртуализации больше нет.

Dell Inspiron 14-3452 - укрощение строптивого

Принесли ноутбук 2015-го года выпуска (Celeron N3050/4GB RAM/500GB HDD), который нужно было привести в порядок. Судя по виду, он использовался мало, но, тем не менее, имел одну ярко выраженную проблему — при включении он оглушительно пищал и выдавал сообщение, что не может распознать, что за блок питания в него воткнули, поэтому он снижает производительность и не будет заряжать аккумулятор.

Оказалось, что фирма Делл делает блоки питания с микросхемкой, которая по центральному контакту в разъёме передаёт информацию о блоке ноутбуку. Блок питания был оригинальным, и я отнёс его на работу, где прекрасный коллега Геннадий, разобрав блок, прозвонил провод тестером и установил, что центральный провод оборван в районе разъёма. Видимо, за провод либо сильно дёрнули, либо изогнули.

Был заказан новый «кабель для блока питания Dell 4.5x3.0мм с центральным контактом» и впаян на место старого, а корпус блока питания аккуратно склеен изолентой. Ноутбук начал распознавать блок питания как родной, но громкий писк при запуске никуда не делся, к тому же оказалось, что аккумулятор сдох окончательно — он не заряжался, даже простояв воткнутым в розетку всю ночь.

Из-за неисправности аккумулятора нельзя прошить новый BIOS — для этого нужно как минимум 10% заряда. Я заказал новую батарею и SSD Samsung 870 EVO 500GB на замену медленной хрустящей штатной Тошибы. Но вернёмся к оглушительно громким сигналам POST.

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

Пять коротких сигналов означают, что разряжена батарейка CMOS (CR2032). После её замены, для чего пришлось разбирать ноутбук почти полностью, он, наконец, начал включаться бесшумно.

Жёсткий диск приехал, и я поставил в качестве системы Windows 10 Home 22H2 x64, которую собрал с помощью сайта uupdump.net. Что приятно, система активировалась сама без каких-либо действий с моей стороны. Всё вроде бы нормально, но операционка даже после всех обновлений почему-то ни в какую не видела микрофона. В BIOS никаких настроек по этому поводу нет, Xubuntu Linux, загруженный с флешки, тоже ничего не увидел, что косвенно указывает на то, что проблема может быть и аппаратной, хотя выглядит это очень странно. Я решил отложить вопрос с микрофоном до прошивки нового BIOS.

Наконец, я получил аккумулятор. Я брал не самый дешёвый, а тот, где было написано «оригинал» или что-то подобное, на Озоне есть такой фильтр. Установил его в ноутбук — и при загрузке получаю предупреждение, что батарея не рекомендована для этой системы и заряжаться она не будет.

Изображение без описания

Тем не менее, аккумулятор нормально работает и заряжается. Единственная проблема — для загрузки системы теперь нужно нажимать на кнопку Continue на экране этого предупреждения про батарею. Но фокус стоит уже на ней, поэтому надо просто нажать клавишу «ввод».

Информация о новом аккумуляторе из HWInfo:

Battery #0

[Общие свойства]
    Имя устройства: DELL 991XP55
    Имя производителя:  Samsung SD
    Серийный номер: 708
    Уникальный идентификатор:   708Samsung SDDELL 991XP55
    Химия:  
    Расчетная мощность: 32560 mWh
    Полная заряженная емкость:  32560 mWh
    Уровень износа: 0.0 %

[Текущее состояние питания]
    Состояние питания:  Разрядка
    Текущая вместимость:    29230 mWh (89.8 %)
    Текущее напряжение: 15.895 V
    Скорость разряда:   -5535 mW 

Ну, батарейка есть, теперь можно и BIOS прошивать. Скачал последнюю версию 4.4.0, доступную для этого ноутбука, запускаю. Что?

Изображение без описания

Система несовместима сама с собой! Опять полез в поиск и нашёл обходной путь. Оказывается, есть недокументированный ключ запуска /writehdrfile, который извлекает из .exe файл .hdr, подходящий для прошивки альтернативным способом.

rem Перейти в рабочий каталог (здесь: C:\temp)
cd C:\temp
rem Извлечение BIOS из exe-файла
Inspiron_3452_3552_4.4.0.EXE /writehdrfile

Потом нужно залезть на сайт American Megatrends, которая пишет биосы, зайти в раздел Developers → Tools & Utilities → BIOS / UEFI и скачать там Aptio V AMI Firmware Update Utility. Так как система у нас 64-битная, надо распаковать из скачанного архива afu\afuwin\64\AfuWin64.zip\AfuWin64\AFUWINx64.exe в каталог, где лежит наш .hdr. В оригинальном описании обходного пути прошивка запускается после загрузки компьютера под DOS, но в этом нет никакой необходимости, всё прекрасно делается и из-под Windows.

Наконец-то добрались и до самой прошивки:

rem Сохранить старый BIOS в файл
AFUWINx64.exe oldBios.rom /O

rem Сравнение GUID старого и нового биосов
AFUWINx64.exe /S
AFUWINx64.exe Inspiron_3452_3552_4.4.0.hdr /U
rem Проверить процесс без реальной прошивки
AFUWINx64.exe Inspiron_3452_3552_4.4.0.hdr /D

rem Прошить новый BIOS
AFUWINx64.exe Inspiron_3452_3552_4.4.0.hdr

Успешный результат прошивки

После перезагрузки новый BIOS требует ввести номер модели, но вводить его некуда — это какой-то мелкий глюк, впоследствии не проявляющийся. Но главное — Windows, загрузившись с новой прошивкой, узрел микрофон и ещё несколько устройств, которые он спокойно установил самостоятельно без посторонней помощи.

Признаться, я не припомню в своей практике настолько капризной машинки. Тем не менее, остались только мелкие недостатки, а именно:

  • Предупреждение о неоригинальном аккумуляторе, требующее нажатия Enter для дальнейшей загрузки.
  • Не работают клавиши регулировки яркости (F11-F12). Советы в интернете включать-выключать устройства видеоадаптера и монитора ни к чему не приводят.

Вот он, этот тип гражданской наружности после всех манипуляций, лет 5-7 ещё может проработать:

Стоимость деталей:

  1. Аккумулятор — 2857 руб.
  2. Жёсткий диск — 3539 руб.
  3. Провод БП — 335 руб.
  4. Батарейка CR2032 — 159 руб.

Итого: 6890 руб.

P. S. Процессор N3050 по сегодняшним меркам очень медленный — Youtube, например, сильно тормозит. Дело в том, что стандартно вещание там идёт в формате VP9, для которого у этого процессора семейства Braswell (8 поколение) нет аппаратного декодера. Чтобы заставить браузер выбирать видео в формате H.264, для которого у N3050 декодер есть, я установил расширение h264ify. Не сказать, чтобы проблема вообще исчезла, но нагрузка на процессор упала на 15-20 процентных пунктов и работать стало получше.

Нагрузка при воспроизведении VP9
Нагрузка при воспроизведении AVC

Автоматизация установки SSL-сертификата на Cisco ASA

Пересадить всю контору на сертификаты Let’s Encrypt оказалось не очень сложно — certbot на реверс-прокси работает, сертификаты после перевыпуска лепятся вместе со своими ключами и кладутся в нужный каталог скриптом, лежащим в /etc/letsencrypt/renewal-hooks/deploy, а в определённое время в cron срабатывает команда, которая при наличии новых сертификатов перечитывает конфигурацию сервера.

На некоторых сервисах, которые выставлены в интернет напрямую, например, сервера видеоконференций, работает свой бот и он обновляет сертификаты локально, но иногда есть нюансы — например, на сервере TrueConf 80-й порт, который требуется для обновления сертификата, занят, и приходится подкручивать /lib/systemd/system/certbot.timer на еженедельный запуск где-то в глухой ночи, а в юнит-файле /lib/systemd/system/certbot.service рисовать следующее, чтобы стопорить службу, занимающую порт, и после процедуры стартовать её заново:

ExecStart=/usr/bin/certbot -q renew \
--pre-hook 'systemctl stop trueconf-web' \
--deploy-hook 'cp /etc/letsencrypt/live/tconf.example.com/cert.pem /opt/trueconf/server/etc/webmanager/ssl/custom.crt && \
cp /etc/letsencrypt/live/tconf.example.com/privkey.pem /opt/trueconf/server/etc/webmanager/ssl/custom.key && \
chown trueconf:trueconf /opt/trueconf/server/etc/webmanager/ssl/custom.\*' \
--post-hook 'systemctl start trueconf-web'

Окно ввода логина и пароля VPN на веб-странице Cisco ASA

Последним бастионом оставался довольно почтенного возраста аппаратный шлюз Cisco ASA, который со всеми этими новомодными удостоверяющими центрами работать не умеет. Так как раньше покупался wildcard-сертификат на год и вставлялся туда руками, проблем его менять не было, кроме оскорбления здравого смысла при виде очередного рассовывания этого несчастного сертификата по всем серверам и раздумий, куда его ещё забыли скопировать. Но так как Let’s Encrypt выпускает сертификаты на 90 дней, ручная установка выглядит совсем уж неуместной, и автоматизация совершенно необходима.

Let’s Encrypt даёт возможность выпускать и wildcard, но для него нужно автоматизировать ещё и создание TXT-записей в DNS через API, что усложняло задачу. Для нашего nic.ru существует программа, но эта схема мне показалось чересчур усложнённой, к тому же, у компании не так много доменов, в случае компрометации сертификата не будет затронуто сразу всё, тем более, что в один сертификат можно поместить сразу несколько альтернативных имён (SAN), что позволяет сократить общее количество выпускаемых сертификатов.

После небольшого гуглежа я обнаружил в некотором роде бриллиант — инструмент для автоматизации работы с интерактивным вводом expect. То есть, пишешь, что должно появиться в командной строке, а потом то, что нужно ввести в ответ. Так как это не bash, а другой интерпретатор, основанный на языке TCL (Tool Command Language), у него свой шебанг — #!/usr/bin/expect -f.

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

На сервере, куда будет приходить 80-й порт и где будет происходить всё последующее, понадобятся 3 файла: скрипт сборки сертификата в нужный формат (pkcs12, закодированный в base64), запускаемый сертботом после его перевыпуска, который, в свою очередь, запускает скрипт expect. Третий файл — это пароль экспорта/импорта сертификата: можно пароль и так захардкодить в первые два файла, но это неудобно. Предполагается, что все действия делаются от учётки root.

# скрипт, выполняющийся при обновлении сертификата
touch /etc/letsencrypt/renewal-hooks/deploy/vpncert-asa.sh
chmod 700 /etc/letsencrypt/renewal-hooks/deploy/vpncert-asa.sh
# скрипт expect
touch /scripts/vpncert-install.exp
chmod 700 /scripts/vpncert-install.exp
# пароль экспорта сертификата для openssl
touch /scripts/vpncert-asa.txt
chmod 600 /scripts/vpncert-asa.txt
# Записать пароль в файл пароля
nano /scripts/vpncert-asa.txt

Содержимое vpncert-asa.sh:

#!/bin/bash

openssl pkcs12 -export \
-password file:/scripts/vpncert-asa.txt \
-in $RENEWED_LINEAGE/fullchain.pem \
-inkey $RENEWED_LINEAGE/privkey.pem \
-out /root/gate.pfx && \

openssl base64 -in /root/gate.pfx -out /root/gate.base64 && \

/scripts/vpncert-install.exp

vpncert-install.exp:

#!/usr/bin/expect -f

set timeout 5
set send_slow {10 .001}
set sshUser "sshuser"
set sshIP "192.168.1.254"
set sshPass "sshPass12345"
set exportPass [exec cat /scripts/vpncert-asa.txt]

spawn ssh -o KexAlgorithms=+diffie-hellman-group1-sha1 -o HostKeyAlgorithms=+ssh-rsa -o StrictHostKeyChecking=no $sshUser@$sshIP
expect "password:"
send -- "$sshPass\r"
expect ">"
send -- "enable\r"
expect "Password:"
send -- "$sshPass\r"
expect "#"
send -- "configure terminal\r"
expect "(config)#"
send -- "no crypto ca trustpoint ca_le\r"
expect {
  "]:" {send -- "yes\r"; exp_continue}
  "(config)#"
}
send -- "crypto ca trustpoint ca_le\r"
expect "trustpoint)#"
send -- "enrollment terminal\r"

expect "#"
send -- "exit\r"
expect "(config)#"

send -- "crypto ca import ca_le pkcs12 $exportPass\r"
expect "itself:"
send -- [exec cat /root/gate.base64]\n
send -s "quit\r"

# % The CA cert is not self-signed.
# % Do you also want to create trustpoints for CAs higher in the hierarchy? [yes/no]:
# OR
# % You already have RSA or ECDSA keys named ca_le.
# % If you replace them, all device certs issued using these keys
# % will be removed.
# % Do you really want to replace them? [yes/no]:
expect {
  "]:" {send -- "yes\r"; exp_continue}
  "(config)#"
}

send -- "ssl trust-point ca_le outside\r"

expect "(config)#"
send -- "exit\r"
expect "#"
send -- "exit\r"
expect eof

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

Вывод во время выполнения работы:

spawn ssh -o KexAlgorithms=+diffie-hellman-group1-sha1 -o HostKeyAlgorithms=+ssh-rsa -o StrictHostKeyChecking=no sshuser@192.168.1.254
sshuser@192.168.1.254's password:
User sshuser logged in to gate
Logins over the last 91 days: 54. Last login: 11:39:24 MSK Jan 9 2023 from 192.168.1.100
Failed logins since the last login: 0.
Type help or '?' for a list of available commands.
gate> enable
Password: **********
gate# configure terminal
gate(config)# no crypto ca trustpoint ca_le
WARNING: Removing an enrolled trustpoint will destroy all
certificates received from the related Certificate Authority.

Are you sure you want to do this? [yes/no]: yes
INFO: Be sure to ask the CA administrator to revoke your certificates.
gate(config)# crypto ca trustpoint ca_le
gate(config-ca-trustpoint)# enrollment terminal
gate(config-ca-trustpoint)# exit
gate(config)# crypto ca import ca_le pkcs12 verySecretPassword12345

Enter the base 64 encoded pkcs12.
End with the word "quit" on a line by itself:
MIIWzwIBAzCCFoUGCSqGSIb3DQEHAaCCFnYEghZyMIIWbjCCEOIGCSqGSIb3DQEH
BqCCENMwghDPAgEAMIIQyAYJKoZIhvcNAQcBMFcGCSqGSIb3DQEFDTBKMCkGCSqG
...
dt/zTsIeIqQq05PLFpOTIzBBMDEwDQYJYIZIAWUDBAIBBQAEIMyVqqTQhaaqlHOH
D3XnctPJR1TYytiVRCaVWuZHz+G0BAiEKmqw9Y6C4AICCAA=
quit
% You already have RSA or ECDSA keys named ca_le.
% If you replace them, all device certs issued using these keys
% will be removed.
% Do you really want to replace them? [yes/no]: yes

Trustpoint 'ca_le' is a subordinate CA and holds a non self-signed certificate.

Trustpoint CA certificate accepted.
WARNING: CA certificates can be used to validate VPN connections,
by default.  Please adjust the validation-usage of this
trustpoint to limit the validation scope, if necessary.
INFO: Import PKCS12 operation completed successfully.
gate(config)# ssl trust-point ca_le outside
gate(config)# exit
gate# exit

Logoff

Connection to 192.168.1.254 closed by remote host.
Connection to 192.168.1.254 closed.

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

Обновил OpenMediaVault на сетевом хранилище

Сетевое хранилище, история которого началась в марте 2018 года, продолжает свою работу. После пересадки в новый корпус в начале 2020-го никаких событий, связанных с ним, не происходило, за исключением замены вышедшей из строя флешки, на которой стояла система, на 120 ГБ SSD Gigabyte GP-GSTF в августе того же года.

На днях я обнаружил, что вышел OpenMediaVault версии 6 — надо обновиться, чтобы не отставать от прогресса и заодно разнообразить своё существование.

Обновление прошло безо всяких проблем, интерфейс стал более крупным, что, видимо, связано с увеличением средней диагонали и разрешения мониторов. Вообще, симпатично.

omv6-login-page.png
omv6-dashboard.png